Transferring tokens
On this page
This tutorial will show you how to transfer SC_Tokens
between the main chain and a sidechain.
Prerequisites
- We will use the sidechain-cli within this tutorial. Download the binary and add it to your shell’s path: https://github.com/input-output-hk/sidechains-tooling/releases.
- Download the bech32 conversion tool binary and add to your shell’s path: https://github.com/input-output-hk/bech32.
- If you have not done so already, create and fund your main chain and sidechain accounts: Create and fund your accounts.
Transfering tokens from a sidechain to the main chain
Transferring SC_Token
from a sidechain to the main chain will require interfacing with the bridge smart contract to lock your desired amount of SC_Token
to be claimed on the main chain. In this guide, you will use RemixIDE to interface with the bridge contract.
Step 01 - Setup contract interface in RemixIDE
Create
/contracts/bridge.abi
with the following contents: bridge.abi
Note: Make sure your Remix-compatible Web3 provider is configured to the EVM sidechain testnet. Eg: MetaMask.
- In Remix, go to Deploy and Run transactions > select Injected Provider (MetaMask) for the environment > Load contract from address (
0x696f686b2e6d616d626100000000000000000000
)
Your RemixIDE will look similar to this with a contract interface:
Step 02 - Lock SC_Token
The lock
function of the bridge contract takes the main-chain recipient’s address, but the recipient address must be converted to bech32 format.
- Convert main-chain address to bech32 format:
./bech32 <<< addr_test1vpzhx6enc57e75n2ygcgdt7cz2c8akt5rk5qaxy7j6vc3ycgly0wh
6045736b33c53d9f526a223086afd812b07ed9741da80e989e96998893 #Returns the conversion
To ensure the address is recognized as a HEX string simply add 0x
to the beginning of the converted address, eg: 0x6045736b33c53d9f526a223086afd812b07ed9741da80e989e96998893
- Determine how many
SC_Token
you want to lock. The amount inSC_Token
has to be a multiple of 10^9. For example, 10^9wei
on the sidechain will be 1SC_Token
on the main chain. Input the amount ofSC_Token
, inwei
, you want to lock: eg,1000000000
Wei == 1SC_Token
. Your Remix should look similar to this:
- Select the
lock
button to initiate the transaction and follow the MetaMask prompts to confirm and sign the transaction.
Note: If the transaction appears to be stuck, ‘pending’ status, or MetaMask shows an invalid balance, try resetting MetaMask and submit the transaction again.
To get the transaction hash or verify that the transaction was successful, you can check MetaMask activity or the Remix console:
Alternatively, you can invoke the
eth_getTransactionReceipt
API method. You can request this until the receipt is returned or transaction times out:
curl -L -X POST -H 'Content-type:application/json' -d '{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [INSERT_RAW_TX],
"id": 1
}' https://faucet.sidechain.evmtestnet.iohkdev.io/ | jq
Step 03 - Wait for transaction to be processed and obtain MerkleProof
- Get the current sidechain status by invoking
sidechain_getStatus
:
curl -L -X POST -H 'Content-type:application/json' -d '{
"jsonrpc": "2.0",
"method": "sidechain_getStatus",
"params": [],
"id": 1
}' https://faucet.sidechain.evmtestnet.iohkdev.io/ | jq -r
This shows on which epoch and phase the lock()
transaction happened. If it happened during epoch N
on epochPhase regular
you can obtain the Merkle proof on epoch N
since epochPhase changes to handover
. If it happened during epoch N
on epochPhase closedTransactionBatch
or handover
, you can obtain the Merkle proof on epoch N+1
since epochPhase changes to handover
.
- Get transaction index for the epoch the lock transaction will be processed by invoking the
sidechain_getOutgoingTransactions
API method:
curl -L -X POST -H 'Content-type:application/json' -d '{
"jsonrpc": "2.0",
"method": "sidechain_getOutgoingTransactions",
"params": [<N or N+1>],
"id": 1
}' https://faucet.sidechain.evmtestnet.iohkdev.io/ | jq
Example output:
{
"jsonrpc": "2.0",
"result": {
"transactions": [
{
"value": "0x1",
"recipient": "0x6041e633c6b54572165a1563291c147dadb803667c99fc8c55ff3762fb",
"txIndex": 0
}
]
},
"id": 1
}
To obtain the merkleProof
matching the recipient and amount used to lock tokens, proceed as follows.
- Wait until the epochPhase changes to
handover
of epochN
orN+1
and obtain the Merkle proof for your lock action by invoking thesidechain_getOutgoingTxMerkleProof
API method:
curl -L -X POST -H 'Content-type:application/json' -d '{
"jsonrpc": "2.0",
"method": "sidechain_getOutgoingTxMerkleProof",
"params": [<N or N+1>, <txIndex>],
"id": 1
}' https://faucet.sidechain.evmtestnet.iohkdev.io/ | jq
Example:
curl -L -X POST https://faucet.sidechain.evmtestnet.iohkdev.io/ -H 'Content-type:application/json' -d '{"jsonrpc": "2.0", "method": "sidechain_getOutgoingTxMerkleProof", "params": [1295, 1], "id": 1}' | jq
{
"jsonrpc": "2.0",
"result": {
"proof": {
"bytes": "0xd8799fd8799f0101581d6045736b33c53d9f526a223086afd812b07ed9741da80e989e96998893d8799f5820772485d60f6744cf252f26560413aae8d28c82a88b1c77eede792f28965f4e79ffff9fd8799f005820ed69142610619b748ec5cd657e418c1c891c3a176900376d12db0b3c406a0a38ffffff",
"info": {
"transaction": {
"value": "0x1",
"recipient": "0x6045736b33c53d9f526a223086afd812b07ed9741da80e989e96998893",
"txIndex": 1
},
"merkleRootHash": "0xaacd27079b9c8b8bd17693beccb8997b4b7b1ef97596018d43047a40dab6b021"
}
},
"sidechainEpoch": 1295
},
"id": 1
}
From the return you need to obtain the proof/bytes
and remove the 0x
that is prepended. Call that string merkleProof
.
In the above example d8799fd8799...
is the Merkle proof.
Wait until the epoch changes and the committee handover has happened.
Note: A sidechain epoch is 1 hour; 30 minutes in the regular
phase, 15 minutes in closedTxBatch
phase, and 15 minutes in handover
phase.
The committee handover happens automatically on the testnets by a service (relay) that tries every minute to find epoch signatures, and succeeds after a new epoch has started and the signatures are obtained. On mainnet, the committee handover will be done by anyone who wants, where there will be an incentive to do so. A good way to verify this is to wait until you observe your transaction in the list of signatures to upload:
curl -L -X POST -H 'Content-type:application/json' -d '{
"jsonrpc": "2.0",
"method": "sidechain_getSignaturesToUpload",
"params": [<limit>],
"id": 1
}' https://faucet.sidechain.evmtestnet.iohkdev.io/ | jq
Where limit
= min(limit, number of epochs that are not yet relayed). The default value is 100
, but you can set it to any other number. Normally, when the handover happens at every epoch, it should only show 0 or 1 epochs (the last one). Once you identify that there are no roothashes pending in the list under the epoch that your lock was processed (N
or N+1
), you can claim your tokens. By now the epoch will be N+1
or N+2
, depending on the phase you performed the lock operation in.
Step 04 - Claim SC_Token
- Claim the tokens by submitting a transaction on the main chain with the
merkleProof
you obtained using the sidechain-cli. You will need to sign the transaction with your main chain signing key (ex:payment.skey
):
./sidechain-cli claim-sc-token \
--sc-evm-url https://faucet.sidechain.evmtestnet.iohkdev.io \
--signing-key-file /PATH/TO/payment.skey \
--combined-proof <merkleProof without 0x>
Example output:
{
"endpoint": "ClaimAct",
"transactionId": "1334b3dab421911af68b9393e5cc4756c46c9ab1ac567a57450597e174351a48"
}
🎉 Congratulations! At this point, you have successfully claimed your SC_Token on the main chain.
Transfering tokens from the main chain to a sidechain
Step 01 - Burn SC_Token
To transfer SC_Token from the main chain to a sidechain, use the sidechain-cli to burn main-chain SC_Token.
./sidechain-cli burn-sc-token \
--signing-key-file payment.skey \
--sc-evm-url https://faucet.sidechain.evmtestnet.iohkdev.io/ \
--recipient ae3dffee97f92db0201d11cb8877c89738353bce \
--amount 10
--signing-key-file payment.skey
: Generating a main-chain account creates a.skey
file to sign transactions. The command gives the path to this file.--sc-evm-url https://faucet.sidechain.evmtestnet.iohkdev.io/
: Providing the JSON-RPC API url, or endpoint, to the sidechain network node.--recipient ae3dffee97f92db0201d11cb8877c89738353bce
: Defines the destination address on the sidechain where the SC_Token tokens will appear.--amount 10
: Defines the amount ofSC_Token
(on the main chain) to be burned forSC_Token
(on the sidechain) at the conversion rate ofamount
x10^9
.
The transaction will be stable on the main chain in approximately 12 minutes or 36 blocks. The sidechain will then add it to a produced block and the tokens should appear in the sidechain-account balance:
- Check
SC_Token
token balance using the JSON-RPC API:
curl -L -X POST https://faucet.sidechain.evmtestnet.iohkdev.io/ -H 'Content-type:application/json' -d '{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["0xae3dffee97f92db0201d11cb8877c89738353bce", "latest"],
"id": 1}'
Tip: Balance may be checked on a compatible Web3 wallet configured to the EVM sidechain testnet network.
🎉 Congratulations! At this point, you have successfully burned your main chain SC_Token
for a native sidechain SC_Token
.