-
Notifications
You must be signed in to change notification settings - Fork 219
Description
Below is a proposal to implement a new functionality for the TokenBridge to transfer DAI tokens through the bridge with simultaneous change of the receiver account. It will allow to specify receiver of the tokens.
Background
Currently ordinary TokenBridge operations (not Arbitrary Message Bridging) assume that an account that receives tokens is the same as the account that sends the tokens.
Let's consider the scenario when Alice transfer tokens through the xDai bridge:
- Alice sends xDai to the bridge contract. The contract implicitly called through fallback function extracts Alice's account address from the transaction parameters and generates an event where this address is specified as the receiver of the tokens.
- The TokenBridge oracles confirm this relay request by sending signatures to the bridge contract on the Ethereum Mainnet side.
- The bridge contract transfers corresponding amount of DAI tokens to the Alice's account in the Ethereum Mainnet.
Similar is performed if Alice transfers tokens in the opposite direction from the Ethereum Mainnet to the xDai chain.
- Alice transfers DAI tokens to the bridge contract by calling the
transfermethod on the token contract. - The TokenBridge oracles catch the
Transferevent targeted to the bridge account and consider it as a relay request. The fieldfromof the event data (which is Alice's account address) is used as the receiver account address for this relay request. - The oracles confirm the relay request by sending transactions to the bridge contract on the xDai chain side.
- The bridge contract registers the request (receiver and value) in the block reward contract.
- The new block is minted with participation of the block reward contract as so the receiver account balance is increased by the requested amount of xDai.
These examples demonstrate that it is not possible to explicitly specify a receiver on the step 1 of every scenario. So, another sequence of operations is needed to implement required functionality.
Proposal
In order to implement the Alternative receiver functionality the new scenario is being suggested. Whether a user transfers tokens either from the xDai chain or from the Ethereum Mainnet, the bridge contract should be called explicitly.
For the transfer from the xDai chain it means that the user needs to invoke a special method (e.g. relayRequest) of the bridge contract and specify the receiver of the tokens.
function relayRequest(address _receiver) payable external {
require(_receiver != address(0));
require(msg.value > 0);
// ...
// some code here
// ...
emit UserRequestForSignature(_receiver, msg.value);
} Since the method is payable the corresponding transaction will have both the input data to handle the method invocation and the value of xDai. The bridge contract will use the address specified in the method parameters to notify the oracles about recipient of tokens on another side of the bridge.
The user's actions to transfer tokens from the Ethereum Mainnet consist of two parts:
- The user invokes
approvemethod of the DAI token contract and specifies the bridge account to be allowable to transfer some specific amount of tokens. - Then the user invokes a special method (e.g.
relayRequest) on the bridge contract, specifies the amount of tokens to be transferred through the bridge and the receiver account address.
function relayRequest(address _sender, address _receiver, uint256 _amount) public {
require(_receiver != address(0));
require(_receiver != address(this));
require(_receiver != bridgeAddressOnxDaiChain);
require(_amount > 0);
// ...
// some code here
// ...
bridgeableToken.transferFrom(_sender, address(this), amount);
emit UserRequestForAffirmation(_receiver, amount);
}
function relayRequest(address _receiver, uint256 _amount) external {
relayRequest(msg.sender, _receiver, _amount);
} The bridge contract invoked through the method will collect approved amount of tokens by transferFrom and notify the oracles about recipient of tokens on another side of the bridge.
Similar functionality can be easily extended for any type of supported bridge modes.
- One side of the bridge operates with either a ordinary ERC20 token or a native coins so it is already covered above.
- Another side of the bridge is based on a ERC677 token. Since the bridge transfer is initiated generally with a invocation of
transferAndCallmethod for these tokens, thedatafield of this method can be used to specify the receiver account address.
Let me clarify the second item by using the POA-POA20 bridge as an example.
At this particular moment the tokens are bridged from the Ethereum Mainnet in the following manner:
- Alice transfers POA20 tokens to the bridge contract by calling the method
transferAndCallon the token contract. The bridge contract address is specified as the recipient of the tokens. - The token contract changes the balances of Alice's and the bridge addresses, invokes the
onTokenTransfermethod of the bridge contract. That causes emitting of an event where Alice’s account address is used as the receiver account address for the relay request. - The oracles confirm the relay request by sending signatures to the bridge contract on the POA chain side.
- The bridge contract sends POA to Alice's account.
For both transferAndCall and onTokenTransfer ERC677 standart specifies the field data as the third parameter:
function transferAndCall(address receiver, uint amount, bytes data) returns (bool success);function onTokenTransfer(address from, uint256 amount, bytes data) returns (bool success);So the functionality of these method in the TokenBridge related contracts could be extended to utilize the data field for an alternative receiver address.
If a user need to alter the receiver of tokens on another side of the bridge, the data field must be filled with the address of tokens recipient.
function transferAndCall(address _receiver, uint _amount, bytes _data) external returns (bool success) {
require(_amount > 0);
// ...
// some code here
//
ERC677TokenReceiver(bridgeContract).onTokenTransfer(_receiver, _amount, _data);
// ...
// some code here
//
}function onTokenTransfer(address _from, uint256 _amount, bytes _data) external returns (bool success) {
address recipient = _from;
if(_data.length == 20) {
recipient = bytesToAddress(_data);
}
require(recipient != address(0));
require(recipient != bridgeAddressOnPOAChain);
// ...
// some code here
//
emit UserRequestForAffirmation(_receiver, amount);
}




