Value Transfer

As explained in the Klaytn design section, Service Chain supports value (KLAY, ERC-20, and ERC-721) transfer between parent chain & child chain. This page shows how to enable the value-transfer feature in SCN.

After setting up the EN and SCN, the following procedure is required to enable value-transfer between chains.

  1. Check the addresses of the bridge operator accounts and add KLAY to the bridge operator accounts.

  2. Deploy the bridge contract to the parent/child chains.

  3. Deploy a token (ERC-20 or 721) contract to the parent/child chains. (If you just need KLAY-transfer, you can skip step 3 & 4.)

  4. Register the token contracts with the bridge contracts on the parent/child chains.

  5. Subscribe to the bridge contracts on the parent/child chains.

Before we follow the steps, let's take a look at the high-level system architecture to understand the behind of the mechanism.

System Architecture

Figure 1 shows the system architecture of the Service Chain with bridge/token contracts and bridge nodes.

Below contracts communicate with each other via main/sub-bridge to process user's value transfer requests.

  • Bridge contract

  • ERC-20 contract (if needed)

  • ERC-721 contract (if needed)

Figure 1. Service chain architecture

Bridge Operator Account

For Service Chain, there are two operator accounts: parent chain bridge operator account, service chain bridge operator account. Each operator account is used to sign transactions. If the transaction moves the value to the parent chain, the parent chain bridge operator account signs the transaction. To the child chain, the child chain bridge operator account is used. If a user submits a "request value transfer" transaction, the Sub-bridge creates a "handle value transfer" transaction signed by the bridge operator account. Therefore, the parent chain bridge operator needs enough KLAY in their balance to pay the transaction fee to the parent chain. If the service chain's gas price is set to non-zero, the service chain bridge operator should have KLAY in their balance as well.

Keystore and Password file

When SCN is booted, the keystore files and password files for the parent/child operators are automatically generated if their keys don't exist. If you want to use a specific account as an operator, you can provide the key. Place the below files in the designated path before booting the SCN. The password file should have a password string of the keystore file. The password file name should be the account address of the corresponding keystore file.

files

  • keystore file : UTC--2019-10-21T04-05-41.493850000Z--2ed72a9d7fe5da7672fd21567e07302431649b0b

  • password file : 0x2eD72a9D7fe5da7672fD21567e07302431649B0B

file path

  • Parent chain bridge operator : $datadir/parent_bridge_account

  • Child chain bridge operator : $datadir/child_bridge_account

> pwd
/$dataDIR/child_bridge_account
> ls
0x2eD72a9D7fe5da7672fD21567e07302431649B0B
UTC--2019-10-21T04-05-41.493850000Z--2ed72a9d7fe5da7672fd21567e07302431649b0b
> cat 0x2eD72a9D7fe5da7672fD21567e07302431649B0B
%S~f5qqM38cB47jL%
> cat UTC--2019-10-21T04-05-41.493850000Z--2ed72a9d7fe5da7672fd21567e07302431649b0b
{"address":"2ed72a9d7fe5da7672fd21567e07302431649b0b","crypto":{"cipher":"aes-128-ctr","ciphertext":"6486509e8158bf4984608cbc5562cf2c9a27cd988a98e543731b39251144e633","cipherparams":{"iv":"96d7e5b6a936278c0797faae6cb3d903"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"8928ba41b8228af19390ec881c51452fa3ea973ad2c253ca0f5bc9197a8b24c4"},"mac":"9c8ec63694c20a473e0ea33840e7d16e9f1a20afc52b3244b703a3ac0a66cfa3"},"id":"9ae10527-7fd3-4aae-a4eb-316af211494e","version":3}

Check Bridge Operator Addresses

If you run SCN successfully, you can check the parent/child chain bridge operator address using RPC API like the following.

$ kscn attach ~/kscnd_home/klay.ipc
Welcome to the Klaytn JavaScript console!
instance: Klaytn/vvX.X.X/XXXX-XXXX/goX.X.X
datadir: ~/kscnd_home
modules: admin:1.0 subbridge:1.0 debug:1.0 governance:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 servicechain:1.0 txpool:1.0
> subbridge.parentOperator
"0xA057995175B93Ee0D1bdfA54f078Ad0F0116130b"
> subbridge.childOperator
"0x5C1C757a6Cb6c6FcEFE398674D8209FDA2A74Df4"

You can refer to the subbridge API for more details.

Send KLAY to Bridge Operators

Like anchoring, the parent chain bridge operator needs KLAY to make a value-transfer transaction. If the service chain's gas price is set to non-zero, the service chain bridge operator should have KLAY in their balance as well.

After topping up the operator accounts, you can check their balances like below.

Parent chain bridge operator

$ kscn attach ~/kscnd_home/klay.ipc
Welcome to the Klaytn JavaScript console!
instance: Klaytn/vvX.X.X/XXXX-XXXX/goX.X.X
datadir: ~/kscnd_home
modules: admin:1.0 subbridge:1.0 debug:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> subbridge.parentOperatorBalance
1e+50

Child chain bridge operator

$ kscn attach ~/kscnd_home/klay.ipc
Welcome to the Klaytn JavaScript console!
instance: Klaytn/vvX.X.X/XXXX-XXXX/goX.X.X
datadir: ~/kscnd_home
modules: admin:1.0 subbridge:1.0 debug:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> subbridge.childOperatorBalance
1e+50

Bridge Contract

For the cross-chain value transfer, a bridge contract should be deployed to the parent/child chains. Users can request a KLAY transfer to the bridge contract to send their KLAY to the other chain. Additionally, if token contracts are registered in the bridge contracts, bridge contracts can handle the token transfer between parent and child chains.

Deployment

Sub-bridge provides a bridge contract deployment API. You can deploy bridge contracts to both chains using a single RPC call as below. Before doing this, you should have connected main-bridge and sub-bridge. Please refer to Bridge Configuration to get detailed guideline.

$ kscn attach ~/kscnd_home/klay.ipc
Welcome to the Klaytn JavaScript console!
instance: Klaytn/vvX.X.X/XXXX-XXXX/goX.X.X
datadir: ~/kscnd_home
modules: admin:1.0 subbridge:1.0 debug:1.0 governance:1.0 istanbul:1.0 klay:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 servicechain:1.0 txpool:1.0
> subbridge.deployBridge()
["0x27caeba831d98b5fbb1d81ce0ed20801702f443a", "0x22c41ae528627b790233d2e59ea520be12350eb5"]
> subbridge.listBridge
[{
localAddress: "0x27caeba831d98b5fbb1d81ce0ed20801702f443a",
remoteAddress: "0x22c41ae528627b790233d2e59ea520be12350eb5",
subscribed: false
}]

You can refer to the subbridge API for more details.

subbridge_listBridge shows the bridge contract addresses and their subscription status. Sub-bridge saves the list of bridge contract addresses in a file. On reboot, sub-bridge reloads the bridge contract list from the file.

Subscribing

After deploying the bridge contract, you should make the sub-bridge subscribe to the deployed bridge contracts to enable value transfer. This can be done using another RPC API call, subbridge_subscribeBridge.

> subbridge.subscribeBridge("0x27caeba831d98b5fbb1d81ce0ed20801702f443a", "0x22c41ae528627b790233d2e59ea520be12350eb5")
null
> subbridge.listBridge
[{
localAddress: "0x27caeba831d98b5fbb1d81ce0ed20801702f443a",
remoteAddress: "0x22c41ae528627b790233d2e59ea520be12350eb5",
subscribed: true
}]

Checking Status

Once subscribed, SCN processes users' "request value transfer" transactions automatically. This section explains how to check the bridge contract status.

In a bridge contact, there are two nonces, requestNonce and handleNonce. Unlike in-chain transactions, the sub-bridge can handle a higher nonce request before the lower ones.

  • requestNonce : the number of user's "cross-chain value transfer" requests made to this bridge contract.

  • handleNonce : the highest nonce that the sub-bridge handled.

  • lowerHandleNonce : the lowest nonce that the sub-bridge should handle.

Therefore, if nonces are updated as follows, we can say the cross-chain value-transfers are processed correctly.

  • "handleNonce" and "lowerHandleNonce" of the parent chain bridge contract keep approaching to the "requestNonce" of the child chain bridge contract.

  • "handleNonce" and "lowerHandleNonce" keep approaching to the "requestNonce" of the parent chain bridge contract.

If "handleNonce" equals to the "requestNonce" of the counterpart bridge contract, and the "lowerHandleNonce" is greater than "handleNonce" by 1, then users' requests were all processed.

Log

Below is a typical log output from SCN during normal operation. Every 1 second, the status of bridge contracts are printed.

INFO[10/16,19:37:40 +09] [45] VT : Parent -> Child Chain request=8699 handle=4826 lowerHandle=4826 pending=3873
INFO[10/16,19:37:40 +09] [45] VT : Child -> Parent Chain request=7894 handle=4207 lowerHandle=4207 pending=3687

This log shows the request, handle, lowerHandle, and pending nonces. Each value means like below

  • request : the sum of value-transfer request nonce(s) of all subscribed bridge contract(s).

  • handle : the sum of upper handle nonce(s) of all subscribed bridge contract(s).

  • lowerHandle : the sum of lower handle nonce(s) of all subscribed bridge contract(s).

  • pending : the difference between request and lowerHandle.

RPC API

You can check the status of a bridge contract like below. You can refer to the subbridge API for more details.

> subbridge.getBridgeInformation("0x27caeba831d98b5fbb1d81ce0ed20801702f443a")
{
counterPart: "0x22c41ae528627b790233d2e59ea520be12350eb5",
handleNonce: 0,
lowerHandleNonce: 0,
isRunning: true,
isSubscribed: true,
onServiceChain: true,
pendingEventSize: 0,
requestNonce: 0
}

Token Contract (ERC-20/721)

Service Chain supports ERC-20/721 value transfer as well. To support them, service chain compatible ERC-20/721 token contracts should be deployed on both parent and child chains. For the ERC-20/721 token contract code, you can refer to the Token standard.

Deployment

SCN does not support an API to deploy ERC-20/721 tokens yet. You need to deploy the tokens via caver-js. When you deploy an ERC-20/721 contract, you should use the correct bridge operator account. Use the parent operator account for the main chain deploy, and the child operator for the service chain deploy. If a token contract was deployed with a wrong account, value transferring will not work and you need to deploy the token contract again with the correct account.

Register

After deploying token contracts, you should register the token contracts with the bridge contracts on the parent/child chains like below.

> subbridge.registerToken("0x27caeba831d98b5fbb1d81ce0ed20801702f443a", "0x22c41ae528627b790233d2e59ea520be12350eb5", "0x376b72abe1b29cace831bd3f5acdfa967814c9cd", "0x53160735f7cc6ff75e48619f368bb94daff66a1b")
null

This command registers the child chain token ("0x376b72abe1b29cace831bd3f5acdfa967814c9cd") with the child chain bridge contract ("0x27caeba831d98b5fbb1d81ce0ed20801702f443a"). And the parent chain token ("0x53160735f7cc6ff75e48619f368bb94daff66a1b") with the parent chain bridge contract ("0x22c41ae528627b790233d2e59ea520be12350eb5").

You can refer to the Service Chain API for more details.

Request Value Transfer

This section explains the contract methods that will be invoked by a user to request a value transfer. Request transaction does not allow zero value (KLAY/ERC-20).

KLAY transfer

Users can make a "request value transfer" transaction to the bridge contract using the below methods.

fallback

If a user calls the fallback function of the bridge, this requests a KLAY transfer to the same account address as the requesting user in the counterpart chain.

function () external payable;

requestKLAYTransfer

If a user calls this function with _to, this requests a KLAY transfer to _to address in the counterpart chain.

function requestKLAYTransfer(address _to, uint256 _value, bytes calldata _extraData) external payable

ERC-20 transfer

2-Step request via Bridge contract

Users can make a "request value transfer" transaction to the Bridge contract using the below method after approving the token to the Bridge contract.

function requestERC20Transfer(address _tokenAddress, address _to, uint256 _value,uint256 _feeLimit,bytes memory _extraData) external

1-Step request via ERC-20 contract

Users can make a "request value transfer" transaction directly to the ERC-20 contract using the below method without approving. The ERC-20 contract should implement the function, then.

function requestValueTransfer(uint256 _amount, address _to, uint256 _feeLimit, bytes calldata _extraData) external

ERC-721 transfer

2-Step request via Bridge contract

Users can make a "request value transfer" transaction to the Bridge contract using the below method after approving the token to the Bridge contract.

function requestERC721Transfer(address _tokenAddress, address _to, uint256 _tokenId, bytes memory _extraData) external

1-Step request via ERC-721 contract

Users can make a "request value transfer" transaction directly to the ERC-721 contract using the below method without approving. The ERC-721 contract should implement the function, then.

function requestValueTransfer(uint256 _uid, address _to) external

Collecting Fee for KLAY/ERC-20 transfer

In Service Chain, there is a fee collecting feature for the KLAY/ERC-20 transfer.

It will be updated soon.

Customizing your Bridge Contract

In Service Chain, you can use your own customized Bridge contract that inherits from the original Bridge contract for your own unique service. This section explains how to customize the Bridge contract and presents the example code.

It will be updated soon.