Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative receiver for TokenBridge transfer operations #295

Closed
akolotov opened this issue Oct 3, 2019 · 0 comments · Fixed by #315
Closed

Alternative receiver for TokenBridge transfer operations #295

akolotov opened this issue Oct 3, 2019 · 0 comments · Fixed by #315
Assignees
Labels

Comments

@akolotov
Copy link
Collaborator

@akolotov akolotov commented Oct 3, 2019

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:

image

  1. 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.
  2. The TokenBridge oracles confirm this relay request by sending signatures to the bridge contract on the Ethereum Mainnet side.
  3. 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.

image

  1. Alice transfers DAI tokens to the bridge contract by calling the transfer method on the token contract.
  2. The TokenBridge oracles catch the Transfer event targeted to the bridge account and consider it as a relay request. The field from of the event data (which is Alice's account address) is used as the receiver account address for this relay request.
  3. The oracles confirm the relay request by sending transactions to the bridge contract on the xDai chain side.
  4. The bridge contract registers the request (receiver and value) in the block reward contract.
  5. 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.

image

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.

image

The user's actions to transfer tokens from the Ethereum Mainnet consist of two parts:

  1. The user invokes approve method of the DAI token contract and specifies the bridge account to be allowable to transfer some specific amount of tokens.
  2. 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.

  1. One side of the bridge operates with either a ordinary ERC20 token or a native coins so it is already covered above.
  2. Another side of the bridge is based on a ERC677 token. Since the bridge transfer is initiated generally with a invocation of transferAndCall method for these tokens, the data field 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:

image

  1. 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.
  2. The token contract changes the balances of Alice's and the bridge addresses, invokes the onTokenTransfer method 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.
  3. The oracles confirm the relay request by sending signatures to the bridge contract on the POA chain side.
  4. 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.

image

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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.