@0x/contracts-asset-proxy: Rename IERC20Bridge.transfer() -> IERC20Bridge.withdrawTo().

`@0x/contracts-asset-proxy`: Make `bridgeData` last parameter in `IERC20Bridge.withdrawTo()`.
`@0x/contracts-asset-proxy`: Reuse `PROXY_ID` as `BRIDGE_SUCCESS`.
This commit is contained in:
Lawrence Forman 2019-09-29 17:08:43 -04:00
parent b728d13d8c
commit b50e26dc2a
5 changed files with 67 additions and 31 deletions

View File

@ -34,9 +34,7 @@ contract ERC20BridgeProxy is
using LibBytes for bytes;
using LibSafeMath for uint256;
// @dev Result of a successful bridge call.
bytes4 constant public BRIDGE_SUCCESS = 0xb5d40d78;
// @dev Id of this proxy.
// @dev Id of this proxy. Also the result of a successful bridge call.
// bytes4(keccak256("ERC20BridgeProxy(address,address,bytes)"))
bytes4 constant private PROXY_ID = 0x37708e9b;
@ -75,15 +73,15 @@ contract ERC20BridgeProxy is
uint256 balanceBefore = balanceOf(tokenAddress, to);
// Call the bridge, who should transfer `amount` of `tokenAddress` to
// `to`.
bytes4 success = IERC20Bridge(bridgeAddress).transfer(
bridgeData,
bytes4 success = IERC20Bridge(bridgeAddress).withdrawTo(
tokenAddress,
from,
to,
amount
amount,
bridgeData
);
// Bridge must return the magic bytes to indicate success.
require(success == BRIDGE_SUCCESS, "BRIDGE_FAILED");
// Bridge must return the proxy ID to indicate success.
require(success == PROXY_ID, "BRIDGE_FAILED");
// Ensure that the balance of `to` has increased by at least `amount`.
require(
balanceBefore.safeAdd(amount) <= balanceOf(tokenAddress, to),
@ -109,9 +107,9 @@ contract ERC20BridgeProxy is
view
returns (uint256 balance)
{
(address tokenAddress, ,) = abi.decode(
(address tokenAddress) = abi.decode(
assetData.sliceDestructive(4, assetData.length),
(address, address, bytes)
(address)
);
return balanceOf(tokenAddress, owner);
}

View File

@ -0,0 +1,30 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "../interfaces/IERC20Bridge.sol";
contract ERC20Bridge is
IERC20Bridge
{
// @dev Result of a successful bridge call.
bytes4 constant internal BRIDGE_SUCCESS = 0x37708e9b;
}

View File

@ -19,21 +19,21 @@
pragma solidity ^0.5.9;
contract IERC20Bridge {
interface IERC20Bridge {
/// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
/// @param bridgeData Arbitrary asset data needed by the bridge contract.
/// @param tokenAddress The address of the ERC20 token to transfer.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
/// @return success The magic bytes `0xb5d40d78` if successful.
function transfer(
bytes calldata bridgeData,
/// @param bridgeData Arbitrary asset data needed by the bridge contract.
/// @return success The magic bytes `0x37708e9b` if successful.
function withdrawTo(
address tokenAddress,
address from,
address to,
uint256 amount
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4 success);

View File

@ -19,7 +19,7 @@
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "../src/interfaces/IERC20Bridge.sol";
import "../src/bridges/ERC20Bridge.sol";
/// @dev Test bridge token
@ -50,16 +50,16 @@ contract TestERC20BridgeToken {
/// @dev Test bridge contract.
contract TestERC20Bridge is
IERC20Bridge
ERC20Bridge
{
TestERC20BridgeToken public testToken;
event BridgeTransfer(
bytes bridgeData,
event BridgeWithdrawTo(
address tokenAddress,
address from,
address to,
uint256 amount
uint256 amount,
bytes bridgeData
);
constructor() public {
@ -72,22 +72,22 @@ contract TestERC20Bridge is
testToken.setBalance(owner, balance);
}
function transfer(
bytes calldata bridgeData,
function withdrawTo(
address tokenAddress,
address from,
address to,
uint256 amount
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4)
{
emit BridgeTransfer(
bridgeData,
emit BridgeWithdrawTo(
tokenAddress,
from,
to,
amount
amount,
bridgeData
);
// Unpack the bridgeData.
(

View File

@ -16,12 +16,13 @@ import * as _ from 'lodash';
import {
artifacts,
ERC20BridgeProxyContract,
TestERC20BridgeBridgeTransferEventArgs,
TestERC20BridgeBridgeWithdrawToEventArgs,
TestERC20BridgeContract,
} from '../src';
blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
const BRIDGE_SUCCESS_RETURN_DATA = hexRightPad('0xb5d40d78');
const PROXY_ID = '0xb5d40d78';
const BRIDGE_SUCCESS_RETURN_DATA = hexRightPad(PROXY_ID);
let owner: string;
let badCaller: string;
let assetProxy: ERC20BridgeProxyContract;
@ -162,12 +163,12 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
const opts = createTransferFromOpts();
const logs = await transferFromAsync(opts);
expect(logs.length).to.eq(1);
const args = logs[0].args as TestERC20BridgeBridgeTransferEventArgs;
expect(args.bridgeData).to.eq(encodeBridgeData(opts.assetData.bridgeData));
const args = logs[0].args as TestERC20BridgeBridgeWithdrawToEventArgs;
expect(args.tokenAddress).to.eq(opts.assetData.tokenAddress);
expect(args.from).to.eq(opts.from);
expect(args.to).to.eq(opts.to);
expect(args.amount).to.bignumber.eq(opts.amount);
expect(args.bridgeData).to.eq(encodeBridgeData(opts.assetData.bridgeData));
});
it('fails if not called by an authorized address', async () => {
@ -287,4 +288,11 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
expect(actualBalance).to.bignumber.eq(balance);
});
});
describe('getProxyId()', () => {
it('returns the correct proxy ID', async () => {
const proxyId = await assetProxy.getProxyId.callAsync();
expect(proxyId).to.eq(PROXY_ID);
});
});
});