The Stellar and Ethereum networks are in many ways complementary. Stellar provides simple transactional functionality that is cheap and fast, with transactions costing a small fraction of a cent and consistently taking less than ten seconds to complete. Ethereum provides a complete programming language (Solidity), smart contracts, and data storage, but as a result transactions are orders of magnitude slower and more expensive. What’s more, the cost of transactions on Ethereum is variable with both complexity (code and metadata) and network congestion.
Making an application dual-platform allows it to benefit from the best of both worlds — Stellar’s low cost and high speed, and Ethereum’s power and flexibility. But this requires that tokens can be moved safely from one blockchain to another without loss or duplication.
Because metadata on Stellar is limited to an asset and a 32-character metadata field — and large amounts of metadata becomes infeasibly expensive on Ethereum when the tokens are of relatively small real value — the bulk of the metadata is stored in IPFS.
Stellar transactions store the token ID using the metadata field, linking back to the IPFS address for the full token data. They can optionally store additional numeric metadata fields using alternate asset types.
Ethereum uses an ERC721 contract that allows key metadata to be stored directly in the blockchain without needing to refer to IPFS. Coin ID and value, batch ID, sequence and count, and direct links to the IPFS metadata and the corresponding API endpoint (following the ERC721 metadata standard).
The IPFS metadata is always present, so when moving from Stellar to Ethereum we can rely on it to fill in the additional fields. The core, immutable metadata is written to the ERC721 token as well so that it can be used directly by Ethereum smart contracts. For example, the nominal value of the token can be used by a smart contract managing token sales, auctions, or trades, and the batch and sequence can control uniqueness.
The Ethereum and Stellar blockchains are entirely separate entities, and a token cannot truly leave either network. So the process of transferring tokens is one of careful, auditable bookkeeping. The requirements are:
- No token can be lost — the transfer from one network to the other should succeed fully or fail such that all changes are reverted.
- No token can be duplicated — if a token is transferred to another network, it is no longer available on the original network.
- Transactions are verifiable — any third party should be able to inspect the respective blockchains and come to the same conclusion as to the ownership of any token.
The Simple Case
In the primary use case, tokens are initially created in Stellar wallets that are delegated to the application. Advanced users who wish to hold token in their personal wallet (such as Metamask) or trade on exchanges such as Rarebits or Opensea, or decentralised networks such as 0x, would need to first transfer their tokens to Ethereum.
The simplest way to handle this is using a conventional database as the control mechanism, and publish the transactional notations to IPFS.
Simple Flow Example
- An annotation is made in the database and on IPFS that the specified token is to be transferred from the user’s Stellar wallet to the desired Ethereum wallet.
- A transaction is opened on the database and on Stellar simultaneously to move the token to a designated holding wallet. Tokens in the holding wallet are unavailable to users or to normal application transactions.
The Stellar transaction carries the value of the token (in the application’s defined asset) and the token’s unique hash.
- When the transaction completes on Stellar, the database transaction is automatically committed, and a second annotation is made in the database and published to IPFS.
The application data and IPFS are updated to show that there is a pending transaction on the token and no other operations are possible until it completes.
- A new annotation is added to the database and published to IPFS showing that the token is being transferred from the holding wallet on Stellar to Ethereum.
- A transaction is posted to the ERC721 contract to create the token on Ethereum.
- The resulting transaction ID is posted to the database and published to IPFS.
- At this point, transactions can no longer be processed in lockstep, as the processing times are both long and unpredictable. Instead, we use an Ethereum blockchain scanner to monitor the transaction ID for verification of success or failure.
(In practice, we actually track all Ethereum transactions relating to the application’s ERC20 and ERC721 tokens, so no separate task needs to be run to track this particular transaction.)
- When the scanner sees verification of the transaction, we clear the pending status in the application database, and publish a final annotation to confirm that the token is now live on the Ethereum network.
Failure Modes and Error Handling
- If an annotation for a pending transaction for the token already exists in the database, the transaction will fail immediately. If the transaction has failed and needs to be retried, it is necessary to wait for confirmation of the failure to be processed through the blockchain scanner and for the database to be updated.
- If the transfer to the holding wallet fails on Stellar, the database transaction is rolled back, and a failure annotation is made in the database and published to IPFS. (The database annotations are made in an independent transaction and are not rolled back.)
In this unusual case, we can provide immediate feedback to the user via the application or API.
- If we suffer a local server failure during the Stellar processing window, we will be left with an annotation of the transaction, and no subsequent annotation.
If there are any such orphan annotations found on recovery, we can verify their status against the Stellar blockchain, and choose to either restart or revert the transaction.
- If we receive a verified failure on the Ethereum transaction, we can retry the transaction automatically. It may be that the Ethereum network was temporarily congested, or that the gas allocated was too low.
In either case, we will create a failure annotation and a retry annotation in the database and IPFS, and wait again on verification in the blockchain scanner.
- If the Ethereum transaction cannot be processed in a timely manner — if the Ethereum network is severely congested or gas prices are excessive, as was seen for several days in August 2018 — we can instead choose to completely unwind the transaction and return the token to the user’s Stellar wallet.
However, this must wait for confirmation of failure on the Ethereum transaction, which in severely congested conditions may itself take hours. While the transaction is still under way on Ethereum it is not possible to cancel it; it can be overridden with a higher gas fee, but that doesn’t help if the gas fee is excessive due to network congestion.
More Complex Cases
In this application it is envisaged that a token once transferred to Ethereum for trading will remain on the Ethereum network. However, it is equally possible to transfer the token back to the Stellar network via a reverse process.
The token is transferred to a smart contract designating the target Stellar wallet, and the blockchain scanner initiates a transaction on the Stellar network to return the previously held token from the holding wallet to the destination user wallet.
This can fail in the following cases:
- If the transfer to the smart contract fails, it is handled by Ethereum, with no need for the gateway to intercede. This applies both to Ethereum network failures, and transfers that are rejected by the smart contract, for example, invalid ERC721 tokens.
- If the destination wallet does not exist on Stellar, it is possible to tell the smart contract to return the original token.
If tokens are transferred in both directions, a token might already exist on the Ethereum network when a transfer is initiated from Stellar.
In this case, the token will already be held in a smart contract. Rather than using the ERC721 contract to generate the token — which would fail due to uniqueness constraints on the tokens — we instead instruct the smart contract to release the token to the designated Ethereum wallet.
Several use case applications that feature Andrew’s Stellar to Ethereum Gateway will be presented at the NFT.NYC Non-Fungible Tokens event on February 20 at the PlayStation Theater, Times Square, New York.
Developer tickets are available on NFT.NYC with the code NFTDEV