ERC-6358 크로스체인 토큰 상태 동기화 (Cross-Chain Token States Synchronization)

Review · 토큰 · 2023-01-17 작성

여러 체인에 배포된 컨트랙트가 같은 토큰 장부를 복사본처럼 함께 기록하게 하는 표준입니다. 토큰을 다른 체인으로 옮기는 대신 모든 체인에서 상태를 동기화합니다.

왜 필요한가

지금의 토큰 브리지는 토큰을 한 체인에서 다른 체인으로 옮기는 방식이라 같은 자산이 체인마다 조각나는 파편화(fragment) 문제가 생깁니다. 안전은 더 심각한 문제입니다. 이더리움의 이더(ETH)를 브리지로 다른 체인에 보냈는데 그 체인이 멈춰 버리면 사용자는 그 ETH를 잃게 됩니다. 이 표준은 옮기기(transfer)가 아니라 동기화(synchronization)를 택합니다. 토큰의 상태를 여러 체인의 컨트랙트가 똑같이 기록하고 신뢰가 필요 없는 오프체인 동기화 프로그램이 체인 사이의 기록을 맞춰 줍니다. 이렇게 하면 다른 체인이 전부 멈추더라도 이더리움만 돌아가면 사용자의 자산은 사라지지 않습니다. 원문은 이 방식으로 파편화 문제가 풀리고 여러 체인에 걸친 사용자 자산의 보안이 크게 높아진다고 설명합니다.

구현해야 하는 것

심층 설명

오머니버스 계정(o-account)

이 표준은 모든 체인에서 공통으로 쓰는 전역 사용자 식별자를 두도록 하며 이를 오머니버스 계정(Omniverse Account, 줄여서 o-account)이라고 부릅니다. o-account는 타원곡선 secp256k1로 만든 공개키로 표현하는 것을 권장합니다. 체인마다 주소 체계가 다르므로 환경별 매핑 방식을 권장하는데, 가장 단순한 구현은 secp256k1 공개키에서 해당 환경의 계정 주소로 가는 매핑과 그 역방향 매핑, 두 개를 만드는 것입니다. 원문은 공개키를 계정에 바인딩해 계정 주소에서 공개키를 바로 얻을 수 있는 Flow의 계정 시스템을 대표 예로 듭니다.

o-트랜잭션 데이터 구조 ERC6358TransactionData

모든 o-트랜잭션은 ERC6358TransactionData 구조체로 기술해야 합니다(MUST). 필드는 여섯 개입니다. nonce는 계정이 보낸 o-트랜잭션의 번호로, 현재 논스가 k이면 다음 유효한 논스는 k+1이며 더 많은 블록체인 기술 스택과의 호환성을 위해 uint128로 정의해야 합니다. chainId는 o-트랜잭션이 시작된 체인으로 uint32입니다. initiateSC는 거래가 처음 시작된 컨트랙트 주소로 bytes, from은 거래에 서명한 오머니버스 계정으로 bytes, payload는 개발자가 정의하는 비즈니스 로직 데이터를 인코딩한 bytes, signature는 위 정보 전체에 대한 서명으로 bytes입니다.

payload 인코딩: Fungible과 NonFungible

payload에는 토큰 동작이 담깁니다. 대체가능 토큰은 Fungible 구조체(op uint8, exData bytes, amount uint256)를, NFT는 NonFungible 구조체(op uint8, exData bytes, tokenId uint256)를 인코딩하는 것을 권장합니다. op는 동작 종류로 0부터 31까지는 예약값, 32부터 255까지는 커스텀값입니다. op 0은 from 계정이 exData에 적힌 계정으로 amount만큼 전송(NFT는 tokenId 전송), op 1은 exData 계정으로 민트, op 2는 from 자신의 토큰 소각입니다. exData는 op가 0과 1일 때 받는 계정을 담고 op가 2일 때는 비어 있습니다.

서명 생성 방식

signature는 구조체의 나머지 정보에 대한 서명이며 bytes로 정의해야 합니다. 생성 방식으로 두 가지가 제시됩니다. 하나는 op, exData, amount(NFT는 tokenId)의 원시 바이트를 이어 붙여 payload를 만들고 다시 nonce, chainId, initiateSC, from, payload를 이어 붙인 전체를 keccak256으로 해시하는 방식입니다. 다른 하나는 EIP-712에 따라 구조화된 데이터로 캡슐화하는 방식입니다. 둘 다 선택 사항(OPTIONAL)이고 마지막에 해시값에 서명하는 점은 같습니다.

IERC6358 인터페이스와 선택 확장

표준을 따르는 컨트랙트는 IERC6358을 반드시 구현해야 합니다. sendOmniverseTransaction은 signature, nonce, payload의 검증을 반드시 구현해야 하고 호출될 때 TransactionSent 이벤트를 반드시 발생시켜야 합니다. 중요한 제약으로 이 함수는 o-트랜잭션을 보내는 용도일 뿐이며 실행을 이 함수 안에서 해서는 안 되고(MUST NOT), 실제 실행은 다른 함수에서 일정 시간 지연 후에 하는 것을 권장합니다. 계정별 논스를 관리하는 맵을 두는 것도 권장합니다. 조회 함수로 getTransactionCount, getTransactionData, getChainId가 있습니다. 선택 확장으로 대체가능 토큰용 IERC6358Fungible(omniverseBalanceOf)과 NFT용 IERC6358NonFungible(omniverseBalanceOf, omniverseOwnerOf)이 있으며, 기존 ERC-20, ERC-721과 조합해 구현할 수도 있습니다.

논스 두 개로 맞추는 전역 일관성

논스는 두 곳에 있습니다. o-트랜잭션 데이터 안의 논스와, 각 체인의 ERC-6358 컨트랙트가 계정별로 관리하는 계정 논스입니다. 동기화할 때 둘을 비교해 검증합니다. 사용자가 한 체인에서 논스 k+1인 o-트랜잭션을 공개하면 다른 체인의 계정 논스는 아직 k이므로, 오프체인 싱크로나이저가 이 차이를 발견해 데이터를 전달합니다. 싱크로나이저는 보상 때문에 앞다퉈 전달하며 보상 전략(수수료, 채굴 방식 등)은 토큰 배포자가 정합니다. 모든 체인의 컨트랙트가 서명을 검증하고 대기 시간이 끝난 뒤 실행하면, 모든 체인에서 계정 논스가 k+1이 되고 잔액 상태도 같아집니다. 이렇게 토큰 상태의 궁극적 일관성이 보장됩니다.

아키텍처와 제안 상태

원문은 여러 체인에 배포된 ERC-6358 컨트랙트를 추상 노드(Abstract Node)라고 부릅니다. 각 체인의 추상 노드가 기록한 상태는 전역 상태의 복사본으로 볼 수 있고 궁극적으로 일치합니다. 싱크로나이저는 한 체인의 컨트랙트가 공개한 o-트랜잭션을 다른 체인들로 나르는 오프체인 프로그램인데, 다른 사용자의 서명이 붙은 데이터를 전달만 하므로 신뢰가 필요 없습니다(trustless). 한편 이 제안의 상태는 Review입니다. 아직 검토 단계라 내용이 바뀔 수 있는 제안이라는 점을 감안해야 합니다.

참조 구현

원문은 secp256k1 공개키로 표현한 오머니버스 계정 예시와 그에 대응하는 개인키 예시를 제공합니다. 또 IERC6358, IERC6358Fungible, IERC6358NonFungible 인터페이스 구현 예시, 공통 도구 라이브러리(OmniverseProtocolHelper), ERC-6358 대체가능 토큰과 NFT의 구현 예시를 EIP 저장소의 assets 경로에 함께 제공합니다. ERC-6358 토큰은 ERC-20, ERC-721과 조합해 쓸 수 있다고 명시합니다.

쓸 때 주의할 점

ERC 원문 · ← ERCs