ChainRunners 기술 리포트

Bifrost
바이프로스트
Published in
13 min readDec 1, 2021

What is ChainRunners?

ChainRunners는 블록체인 생태계에서 모든 서비스의 지능을 높여서 서비스끼리 손쉽게 연결되고 사용자가 느끼는 간극(gap)과 불편함을 최소화하기 위하여 개발되었습니다. 블록체인은 사용자가 직접 해결해야하는 간극은 너무 많습니다. 많은 이익을 가져다 주는 DeFi나 NFT서비스 를 사용하기 위해서는 crypto-wallet, 금융지식 뿐만이 아니라 때때로 smart contract를 직접 작성하도록 요구하기도 합니다. Money Lego를 자랑하는 새로운 세상에도 여전히 사용자가 직접 하나씩 익혀가며 모든 것을 해야하는 상황입니다.

[그림 1]. What is a ChainRunner?

1. ChainRunner Engine: A Hub for Users and Services

ChainRunner Engine는 단독으로 사용자, 서비스(web) 그리고 인터넷(또는 offchain)을 연결합니다. 변화무쌍한 블록체인 생태계에서 생존하기 위해서 javascript가 가능한 web환경이면 어디서나 동작할 수 있습니다.

서비스와는 유연성을 높이기 위해서 ChainRunners가 이해하는 언어(뒤에 소개될 Taster)를 주고 받습니다. 여러 단계가 필요한 블록체인의 복잡한 서비스를 고수준에서 단순하게 명령할 수 있습니다. (e.g. “서비스에 pooling한 자산을 다른 자산으로 migration하기”) ChainRunner Engine은 명령을 해석해서 필요한 작업들로 분해하고 사용자에게 각 단계를 진행해도 될지 확인합니다. 만일 사용자가 ChainRunners의 언어를 이해하고 (어렵지 않습니다!) 바로 사용한다면 본인이 원하는 작업을 지시할 수 있습니다.

사용자와는 지갑으로 연결됩니다. 블록체인에서 모든 동작은 사용자의 서명을 통해서 안전하게 일어나야 됩니다. ChainRunner Engine은 필요한 작업을 사용자의 Biport나 Metamask 등의 지갑에 요청하여 안전하게 사용자의 서명을 받습니다.

한편 Offchain이라 할 수 있는 블록체인의 바깥 서비스와도 연계됩니다. 예를 들어, 차익거래를 원하시는 분들은 외부의 Gelato, Defender와 같은 블록체인 전용의 Autotask 서비스와 연계하거나 차후에 발표될 ChainRunner 서비스와 연계하여 특정 조건이 달성된 경우 원하는 명령을 실행할 수 있습니다. 토큰 스왑 때에도 offchain에 있는 오라클이나 거래소 가격을 참조하며 거래하는 안전장치를 가질 수 있습니다. 인터넷을 이용한 자동화는 언제나 발전 중입니다. IFTTT와 같은 서비스와 연계하여 트위터나 인스타그램에 새로운 피드가 있을때, 블록체인 거래를 수행하는 방법도 생각할 수 있겠죠.

2. The Lightweight Architecture Built With F#

ChainRunners 전체는 안전성과 고성능으로 유명한 함수형 언어인 F#으로 개발되었지만, 일부 기능을 떼어서 블록체인 서비스 어디서든 동작할 수 있는 엔진 형태로 만들기 위하여 영리한 구조를 가지게 되었습니다. ChainRunner Engine은 .NET의 Blazor 구조를 참조하여 .NET Framework를 WASM로 구성하고, 이 위에 ChainRunners의 모듈들을 탑재하는 방법으로 최종적으로는 WASM 바이너리로 만들어 냅니다. 따라서 웹브라우저나 javascript가 실행 가능한 곳은 어디서든 동작합니다. 또한 단독 컴포넌트로 서버에 종속적이지 않기 때문에 서버 문제로 서비스가 멈추는 등의 단일 장애점 문제가(Single Point Failure) 발생하지 않습니다.

[그림 2]. ChainRunner Software Stack

ChainRunner Engine의 구조는 여러 모듈들로 구성되어 있습니다. (그림 2) Taster는 ChainRunner Engine만의 유연성 높은 소통 수단입니다. 따라서 Taster와 관련된 모듈이 많습니다. Taster Validator에서는 입력된 Taster의 문법 및 잘못 작성된 내용(e.g. ETH와 USDT의 수량을 더하는 잘못된 연산)이 없는지 확인합니다. Taster Executor는 일종의 interpreter로서 명령 실행을 총괄합니다. Taster 실행에는 3가지 모듈이 참여합니다. 블록체인과 상호작용을 하는 Blockchain Executor, 블록체인 바깥 세상과의 연결을 담당하는 Offchain Interactor, 사용자의 허락을 구해서 서명을 받는 Wallet Connector가 항상 사용됩니다. 때때로 Taster의 일부가 smart contract가 되어야 할 때가 있습니다. 이때 Transpiler가 자동으로 내용의 일부를 smart contract로 변환합니다. (이 강력한 기능은 추후에 기술 문서로 더 설명될 예정입니다.) 마지막으로 Blockchain Service Model로 각종 블록체인 서비스를 쉽게 사용하기 위한 라이브러리 집합입니다. 이어지는 Taster 소개에 자세히 설명됩니다.

3. Taster: Language for Blockchain Services

사람의 의도를 컴퓨터에게 어떻게 알려 줄 것인가는 컴퓨터 과학에서 항상 고민하는 문제입니다. “내 Ether 예금을 USDT 예금으로 바꿔줘”나 “가격이 떨어질지 모르니 2배 레버리지를 이용해서 Ether를 short position을 잡아줘” 등은 사람이 직접 수행하기 위해서도 이곳저곳을 찾아가면서 여러 단계를 거쳐야 합니다. 코드로 만들어 낸다면 그 양도 어마어마하죠.

그래서 ChainRunner에게 “Taster”라고 불리는 사람의 의도를 충분히 표현할 수 있는 새로운 언어를 만들어 주었습니다. 물론, 컴퓨터가 이해하고 정확하게 표현해야 하기 때문에 프로그래밍 언어의 형태를 갖추기는 하지만, 블록체인의 기능들을 바로 표현할 수 있는 고수준의 언어 입니다. 이렇게 특정한 영역에서만 사용되는 언어를 Domain Specific Language (DSL)이라고 합니다. 이러한 DSL을 사용하면 여러 장점이 있습니다. 우선 고수준의 기능으로 명령하면 되기 때문에 서비스간의 연결성이 높아집니다. 그리고 사람도 쉽게 익히고 이해할 수 있기 때문에 직접 사용하기도 쉽습니다.

Taster 언어를 만들 때에는 여러가지 요소가 반영되었습니다. 필요한 기능은 Solidity로 자동 변환(transpile)되어 smart contract로 배포되어야 하기 때문에 단순함을 유지하면서, Uniswap이나 Compound와 같이 잘 알려진 서비스를 바로 사용할 수 있도록 유연성을 가질 수 있도록 하였습니다. 무엇보다 무척 간단하기 때문에 Python이나 Javascript를 사용해보신 분이라면 reference 페이지를 옆에 두고 바로 시작하실 수 있습니다.

모든 ChainRunner Engine은 Taster 언어로 미리 작성된 Blockchain Service model을 이미 탑재하고 있습니다. (Standard library라고 생각하시면 됩니다.) 즉 ChainRunner가 있는 곳이라면 지원하는 많은 서비스들을 바로 사용하실 수 있습니다. (지원 서비스 목록은 Reference page를 참조하세요.)

Taster를 사용하면 내부적으로 이러한 일들을 수행합니다. 예를 들어 Q에서 제공하는 시나리오 중 하나인 “BiFi Pooling에 BiFi-WETH LP 토큰 예금하기”를 시나리오는 4가지 과정을 가집니다.

  1. 유동성 공급에 사용할 ETH 수량을 결정 합니다.
  2. 스시스왑에서 BiFi 토큰을 구매 합니다.
  3. 스시스왑의 BiFI-WETH Pool에 유동성을 공급합니다.
  4. 유동성 제공의 권리로 받은 LP (SLP)토큰을 BiFi Pooling에 예금합니다.

위 과정은 ChainRunner가 위 세 줄의 Taster 코드로 완료할 수 있습니다. Blockchain Service Model이 스시스왑과 BiFi 등에 대한 기능을 고수준에서 바로 사용할 수 있도록 해줍니다. 실제 내부에서는 어떠한 일이 일어날까요? 대표적으로 맨 첫줄에 있는, 스시스왑에서 BiFi 토큰을 구입하는 과정에서 사용하는 swapEsactETHForTokens()만을 살펴보겠습니다. 스시스왑을 통해서 토큰을 교환할 수 있도록 해주는 역할을 합니다.

  1. 먼저 거래를 트려면 Crypto-wallet에 연결된 계정을 가져와야 합니다. Line 1에서 ChainRunner가 바로 그 작업을 수행합니다. 이제 account 변수는 유저가 현재 연결한 Crypto-wallet 계정을 가지고 있습니다.
  2. 다음은 구입 할 토큰의 smart contract를 알아야 합니다. Line 2에서는 이름이 “bifi”인 토큰의 smart contract를 블록체인으로 부터 얻어 옵니다.
  3. 스시스왑 contract에서 제공하는 여러 스왑 함수는 Path라는 배열로 스왑하려는 토큰 smart contract 리스트를 요구합니다. 우리는 WETH와 bifi를 교환 하기 위해서 두 토큰의 smart contract를 합쳐서 배열로 조합합니다.
  4. 블록체인 기반의 DeFi에서 스왑할때 주의깊게 설정해야 하는 값은 슬리피지(slippage) 입니다. 슬리피지란 스왑요청을 한 시점과 실제 스왑요청이 체인에서 처리되는 시점에 시세변동이 있어서 내가 원하는 거래가로 교환이 이뤄지지 않아 손해보는 경우를 의미합니다. 이를 대비하기 위해서 슬리피지의 제한선을 두도록 합니다. 이 라인에서는 슬리피지 한도를 설정하기 위해서 유저가 정한 WETH (amountIn)으로 얼마만큼의 bifi를 얻을 수 있는지를 미리 계산합니다.
  5. 슬리피지를 방지하기 위한 거래 한도 제한을 계산하기 위해 필요한 정보로 bifi토큰의 decimals 값을 블록체인으로 부터 읽어 옵니다.
  6. 마찬가지로 기본 슬리피지 비율을 얻어 옵니다. (스시스왑의 경우 0.5% 입니다.)
  7. 4,5,6 단계(Line 4,5,6)에서 준비된 값들을 기준으로 유저가 정한 WETH로 거래할 수 있는 bifi의 수량에서 기본 슬리피지 비율을 곱해 거래 제한 금액 (amountOutMin)을 설정합니다. 유저가 요청한 스왑이 블록체인에 도달해서 처리되는 시점에 amountOutMin 값보다 작은 수량의 bifi가 결과값이 된다면 거래를 무효화(transaction revert)하기 위함입니다.
  8. 블록체인에서 처리하는 트랜잭션이 마이너에 의해서 채굴되지 못하고 너무 오랫동안 대기 상태로 머무는 경우 데드라인을 줘서 트랜잭션이 스스로 폐기 될 수 있도록 하는 값입니다. 대부분의 DeFi에서 이 값을 넉넉하게 잡아둡니다. 너무 타이트하게 잡으면 거래 자체가 이뤄지지 않기 때문에 서비스 사용성을 저해 합니다.
  9. 스왑이 완료된 시점에 bifi가 얼마나 확보 되었는지 보여주기 위해서 거래 직전의 잔액을 미리 얻어 옵니다.
  10. 스왑 준비가 모두 끝났기때문에 스시스왑의 swapExactETHForTokens() 함수(Smart contract이기 때문에 함수 입니다.)를 호출해서 ETH와 BiFi를 스왑합니다.
  11. 거래가 끝난 후 추가로 확보된 bifi수량을 얻기위해 현재의 잔액을 얻어옵니다.
  12. 마지막으로 (현재 잔액 — 거래 직전 잔액)을 리턴합니다.

단지 하나의 동작을 위해서도 ChainRunner는 이러한 일들을 대신 수행합니다. 사실 그리고 내부적으로 몇 단계가 더 있습니다. 우리가 들여다 본 프로시저 속에서 호출하고 있는 또 다른 프로시저 들이 보이시죠? 예를 들면, getDefaultSlippage(), getTokenAddr() 같은 것들요. 사실 그들도 내부에는 더 많은 일을 수행하는 Taster의 프로시저로 감싸져 있습니다. 이 과정의 차끝에는 ChainRunner의 Taster Evaluator → Blockchain Executor 로의 흐름이 이어집니다. Blockchain Executor가 블록체인에 있는 smart contract와 통신하고 다시 Taster Evaluator로 데이터를 보내주는 셈이죠. (e.g. 스왑 후 erc20.balanceOf(tokenName)의 리턴 값)

ChainRunner Q

ChainRunner Q는 ChainRunner의 첫번째 주자(runner)로 ChainRunner Engine의 기능을 맛보실 수 있습니다. Q는 여러분의 충실한 집사이자, 블록체인 서비스를 위한 만능 요리사 입니다. 요리책과 같은 UX에서 여러분이 원하는 시나리오를 선택하시면, 클릭 몇번으로 손쉽게 원하는 모든 작업을 완료하실 수 있습니다. 이자농사와 같은 DeFi의 복잡한 기능을 대신 수행 해주기도하고, 다수의 서비스를 오가야 하는 복잡한 시나리오(e.g. 차익거래, 마이그레이션)등도 준비되어 있습니다. 예를 들어, “BiFi-WETH Pooling 에 LP토큰 예치하기”와 같은 작업을 Q는 단 하나의 입력(WETH-BiFi풀에 공급할 WETH의 수량)만 유저에게 받아서 작업을 완료합니다. 재료가 되는 블록체인의 새로운 서비스는 무궁무진하니 요리법 또한 계속 업데이트 될 예정입니다.

[그림 3] ChainRunner Q

당장은 ChainRunners의 가능성을 보여주는 Q이지만, Q는 자체만으로도 지속적으로 발전가능한 프로젝트 입니다. Q가 읽을 수 있는 요리책은 사실 인터넷에서 널리 사용되는 Markdown 파일에 taster 코드를 가미하여 누구나 만들 수 있습니다. 투자에 밝은 분이나 블록체인 서비스의 불편함을 해소해주는 누구나 자신만의 전략이나 방법을 만들어서 공유하고, 공유된 요리책에서 발생한 수익을 함께 나누어가지는 플랫폼으로 발전할 예정입니다. Markdown에 Taster 코드와 함께 전략에 대한 충실한 설명이 함께한다면 BIFROST City에서의 명성과 수익을 얻으실 수 있습니다.

Future of ChainRunners

BIFROST City의 모든 서비스는 예외없이 다른 서비스와의 시너지를 고려해서 만들어집니다. ChainRunners는 Biport, BiFi 등에 탑재되어 각종 다른 서비스를 쉽게 사용하고 연계할 수 있도록 해줄 것입니다. 이후에 BIFROST City에서 출시되는 다른 서비스들은 ChainRunner의 활동 범위를 넓히고 더 많은 일을 할 수 있게 되며, ChainRunner가 있는 곳이라면 어디든 같은 혜택을 받게 됩니다. 서비스이자 플랫폼으로서의 역할을 하는 ChainRunner의 지속적인 발전을 기대해주세요!

--

--

Bifrost
바이프로스트

Bifrost is the ultimate cross-chain L1 blockchain welcoming all DApps! www.bifrostnetwork.com