ERC-6358 Cross-chain token state synchronization (Cross-Chain Token States Synchronization)

Review · Tokens · created 2023-01-17

A standard in which contracts deployed on multiple chains jointly record the same token ledger as if it were a shared copy. Instead of moving tokens to another chain, state is synchronized across all chains.

Why it is needed

Current token bridges move tokens from one chain to another, which causes a fragmentation problem where the same asset is split across different chains. Safety is an even more serious issue. If a user bridges Ethereum's ETH to another chain and that chain stops, the user loses that ETH. This standard chooses synchronization over transfer. Contracts on multiple chains record the same token state identically, and a trustless off-chain synchronization program reconciles the records between chains. This way, even if every other chain stops, as long as Ethereum keeps running, the user's assets do not disappear. The source explains that this approach solves the fragmentation problem and greatly increases the security of user assets across multiple chains.

What to implement

In depth

Omniverse Account (o-account)

This standard establishes a global user identifier shared across all chains, called an Omniverse Account (o-account for short). It is recommended that an o-account be represented by a public key generated with the secp256k1 elliptic curve. Since each chain has a different address scheme, an environment-specific mapping approach is recommended; the simplest implementation is to create two mappings, one from the secp256k1 public key to the account address in that environment, and its inverse. The source cites Flow's account system, which binds the public key to the account so the public key can be obtained directly from the account address, as a representative example.

The o-transaction data structure, ERC6358TransactionData

Every o-transaction must (MUST) be described using the ERC6358TransactionData struct. It has six fields. nonce is the sequence number of the o-transaction sent by the account; if the current nonce is k, the next valid nonce is k+1, and it must be defined as uint128 for compatibility with more blockchain technology stacks. chainId is the chain on which the o-transaction originated, as a uint32. initiateSC is the address of the contract where the transaction was first initiated, as bytes; from is the omniverse account that signed the transaction, as bytes; payload is bytes encoding developer-defined business logic data; and signature is bytes containing the signature over all the above information.

Payload encoding: Fungible and NonFungible

The payload contains the token operation. It is recommended to encode a Fungible struct (op uint8, exData bytes, amount uint256) for fungible tokens, and a NonFungible struct (op uint8, exData bytes, tokenId uint256) for NFTs. op indicates the operation type: values 0 through 31 are reserved, and 32 through 255 are custom. op 0 means the from account transfers amount (or tokenId, for NFTs) to the account specified in exData; op 1 means minting to the account in exData; op 2 means from burns its own tokens. exData holds the recipient account when op is 0 or 1, and is empty when op is 2.

Signature generation method

signature is the signature over the remaining information in the struct and must be defined as bytes. Two generation methods are presented. One concatenates the raw bytes of op, exData, and amount (or tokenId, for NFTs) to form the payload, then concatenates nonce, chainId, initiateSC, from, and payload and hashes the whole with keccak256. The other encapsulates the data as structured data according to EIP-712. Both are optional (OPTIONAL), and in both cases the final step is signing the hash value.

The IERC6358 interface and optional extensions

Contracts conforming to the standard must implement IERC6358. sendOmniverseTransaction must implement verification of the signature, nonce, and payload, and must emit a TransactionSent event when called. An important constraint is that this function is only for sending the o-transaction; execution must not (MUST NOT) happen inside this function, and it is recommended that actual execution take place in a different function after a certain delay. It is also recommended to maintain a map tracking the nonce for each account. The query functions are getTransactionCount, getTransactionData, and getChainId. Optional extensions include IERC6358Fungible (omniverseBalanceOf) for fungible tokens and IERC6358NonFungible (omniverseBalanceOf, omniverseOwnerOf) for NFTs, and these can also be implemented in combination with existing ERC-20 and ERC-721.

Global consistency reconciled through two nonces

There are two nonces. One is the nonce inside the o-transaction data, and the other is the account nonce that the ERC-6358 contract on each chain maintains per account. During synchronization, the two are compared for verification. When a user publishes an o-transaction with nonce k+1 on one chain, the account nonce on other chains is still k, so an off-chain synchronizer detects this discrepancy and relays the data. Synchronizers race to relay it because of the reward, and the reward strategy (fees, mining-style rewards, etc.) is determined by the token deployer. Once contracts on every chain verify the signature and execute after the waiting period ends, the account nonce becomes k+1 on all chains and the balance state matches. This guarantees the ultimate consistency of token state.

Architecture and proposal status

The source calls the ERC-6358 contracts deployed across multiple chains Abstract Nodes. The state recorded by the Abstract Node on each chain can be viewed as a copy of the global state, and they ultimately converge. The synchronizer is an off-chain program that carries o-transactions published by one chain's contract to other chains; since it only relays data bearing another user's signature, it is trustless. Note that this proposal's status is Review. It should be kept in mind that this is still at the review stage and its content may change.

Reference implementation

The source provides an example omniverse account expressed as a secp256k1 public key, along with its corresponding example private key. It also provides, under the assets path of the EIP repository, example implementations of the IERC6358, IERC6358Fungible, and IERC6358NonFungible interfaces, a common utility library (OmniverseProtocolHelper), and example implementations of ERC-6358 fungible tokens and NFTs. It states explicitly that ERC-6358 tokens can be used in combination with ERC-20 and ERC-721.

Things to watch out for

Original ERC · ← ERCs