diff --git a/contracts/asset-proxy/contracts/src/ERC20BridgeProxy.sol b/contracts/asset-proxy/contracts/src/ERC20BridgeProxy.sol index 67b32030a2..8ccc428682 100644 --- a/contracts/asset-proxy/contracts/src/ERC20BridgeProxy.sol +++ b/contracts/asset-proxy/contracts/src/ERC20BridgeProxy.sol @@ -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); } diff --git a/contracts/asset-proxy/contracts/src/bridges/ERC20Bridge.sol b/contracts/asset-proxy/contracts/src/bridges/ERC20Bridge.sol new file mode 100644 index 0000000000..9b9f00f764 --- /dev/null +++ b/contracts/asset-proxy/contracts/src/bridges/ERC20Bridge.sol @@ -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; +} diff --git a/contracts/asset-proxy/contracts/src/interfaces/IERC20Bridge.sol b/contracts/asset-proxy/contracts/src/interfaces/IERC20Bridge.sol index 7cb260eacc..1ee1361fbe 100644 --- a/contracts/asset-proxy/contracts/src/interfaces/IERC20Bridge.sol +++ b/contracts/asset-proxy/contracts/src/interfaces/IERC20Bridge.sol @@ -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); diff --git a/contracts/asset-proxy/contracts/test/TestERC20Bridge.sol b/contracts/asset-proxy/contracts/test/TestERC20Bridge.sol index 4f3240ee5d..e6b3441658 100644 --- a/contracts/asset-proxy/contracts/test/TestERC20Bridge.sol +++ b/contracts/asset-proxy/contracts/test/TestERC20Bridge.sol @@ -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. ( diff --git a/contracts/asset-proxy/test/erc20bridge_proxy.ts b/contracts/asset-proxy/test/erc20bridge_proxy.ts index 1d791f8f6b..22dfe5b1cc 100644 --- a/contracts/asset-proxy/test/erc20bridge_proxy.ts +++ b/contracts/asset-proxy/test/erc20bridge_proxy.ts @@ -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); + }); + }); });