@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:
parent
b728d13d8c
commit
b50e26dc2a
@ -34,9 +34,7 @@ contract ERC20BridgeProxy is
|
|||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
using LibSafeMath for uint256;
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
// @dev Result of a successful bridge call.
|
// @dev Id of this proxy. Also the result of a successful bridge call.
|
||||||
bytes4 constant public BRIDGE_SUCCESS = 0xb5d40d78;
|
|
||||||
// @dev Id of this proxy.
|
|
||||||
// bytes4(keccak256("ERC20BridgeProxy(address,address,bytes)"))
|
// bytes4(keccak256("ERC20BridgeProxy(address,address,bytes)"))
|
||||||
bytes4 constant private PROXY_ID = 0x37708e9b;
|
bytes4 constant private PROXY_ID = 0x37708e9b;
|
||||||
|
|
||||||
@ -75,15 +73,15 @@ contract ERC20BridgeProxy is
|
|||||||
uint256 balanceBefore = balanceOf(tokenAddress, to);
|
uint256 balanceBefore = balanceOf(tokenAddress, to);
|
||||||
// Call the bridge, who should transfer `amount` of `tokenAddress` to
|
// Call the bridge, who should transfer `amount` of `tokenAddress` to
|
||||||
// `to`.
|
// `to`.
|
||||||
bytes4 success = IERC20Bridge(bridgeAddress).transfer(
|
bytes4 success = IERC20Bridge(bridgeAddress).withdrawTo(
|
||||||
bridgeData,
|
|
||||||
tokenAddress,
|
tokenAddress,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
amount
|
amount,
|
||||||
|
bridgeData
|
||||||
);
|
);
|
||||||
// Bridge must return the magic bytes to indicate success.
|
// Bridge must return the proxy ID to indicate success.
|
||||||
require(success == BRIDGE_SUCCESS, "BRIDGE_FAILED");
|
require(success == PROXY_ID, "BRIDGE_FAILED");
|
||||||
// Ensure that the balance of `to` has increased by at least `amount`.
|
// Ensure that the balance of `to` has increased by at least `amount`.
|
||||||
require(
|
require(
|
||||||
balanceBefore.safeAdd(amount) <= balanceOf(tokenAddress, to),
|
balanceBefore.safeAdd(amount) <= balanceOf(tokenAddress, to),
|
||||||
@ -109,9 +107,9 @@ contract ERC20BridgeProxy is
|
|||||||
view
|
view
|
||||||
returns (uint256 balance)
|
returns (uint256 balance)
|
||||||
{
|
{
|
||||||
(address tokenAddress, ,) = abi.decode(
|
(address tokenAddress) = abi.decode(
|
||||||
assetData.sliceDestructive(4, assetData.length),
|
assetData.sliceDestructive(4, assetData.length),
|
||||||
(address, address, bytes)
|
(address)
|
||||||
);
|
);
|
||||||
return balanceOf(tokenAddress, owner);
|
return balanceOf(tokenAddress, owner);
|
||||||
}
|
}
|
||||||
|
30
contracts/asset-proxy/contracts/src/bridges/ERC20Bridge.sol
Normal file
30
contracts/asset-proxy/contracts/src/bridges/ERC20Bridge.sol
Normal 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;
|
||||||
|
}
|
@ -19,21 +19,21 @@
|
|||||||
pragma solidity ^0.5.9;
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
|
||||||
contract IERC20Bridge {
|
interface IERC20Bridge {
|
||||||
|
|
||||||
/// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
|
/// @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 tokenAddress The address of the ERC20 token to transfer.
|
||||||
/// @param from Address to transfer asset from.
|
/// @param from Address to transfer asset from.
|
||||||
/// @param to Address to transfer asset to.
|
/// @param to Address to transfer asset to.
|
||||||
/// @param amount Amount of asset to transfer.
|
/// @param amount Amount of asset to transfer.
|
||||||
/// @return success The magic bytes `0xb5d40d78` if successful.
|
/// @param bridgeData Arbitrary asset data needed by the bridge contract.
|
||||||
function transfer(
|
/// @return success The magic bytes `0x37708e9b` if successful.
|
||||||
bytes calldata bridgeData,
|
function withdrawTo(
|
||||||
address tokenAddress,
|
address tokenAddress,
|
||||||
address from,
|
address from,
|
||||||
address to,
|
address to,
|
||||||
uint256 amount
|
uint256 amount,
|
||||||
|
bytes calldata bridgeData
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
returns (bytes4 success);
|
returns (bytes4 success);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
pragma solidity ^0.5.9;
|
pragma solidity ^0.5.9;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "../src/interfaces/IERC20Bridge.sol";
|
import "../src/bridges/ERC20Bridge.sol";
|
||||||
|
|
||||||
|
|
||||||
/// @dev Test bridge token
|
/// @dev Test bridge token
|
||||||
@ -50,16 +50,16 @@ contract TestERC20BridgeToken {
|
|||||||
|
|
||||||
/// @dev Test bridge contract.
|
/// @dev Test bridge contract.
|
||||||
contract TestERC20Bridge is
|
contract TestERC20Bridge is
|
||||||
IERC20Bridge
|
ERC20Bridge
|
||||||
{
|
{
|
||||||
TestERC20BridgeToken public testToken;
|
TestERC20BridgeToken public testToken;
|
||||||
|
|
||||||
event BridgeTransfer(
|
event BridgeWithdrawTo(
|
||||||
bytes bridgeData,
|
|
||||||
address tokenAddress,
|
address tokenAddress,
|
||||||
address from,
|
address from,
|
||||||
address to,
|
address to,
|
||||||
uint256 amount
|
uint256 amount,
|
||||||
|
bytes bridgeData
|
||||||
);
|
);
|
||||||
|
|
||||||
constructor() public {
|
constructor() public {
|
||||||
@ -72,22 +72,22 @@ contract TestERC20Bridge is
|
|||||||
testToken.setBalance(owner, balance);
|
testToken.setBalance(owner, balance);
|
||||||
}
|
}
|
||||||
|
|
||||||
function transfer(
|
function withdrawTo(
|
||||||
bytes calldata bridgeData,
|
|
||||||
address tokenAddress,
|
address tokenAddress,
|
||||||
address from,
|
address from,
|
||||||
address to,
|
address to,
|
||||||
uint256 amount
|
uint256 amount,
|
||||||
|
bytes calldata bridgeData
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
returns (bytes4)
|
returns (bytes4)
|
||||||
{
|
{
|
||||||
emit BridgeTransfer(
|
emit BridgeWithdrawTo(
|
||||||
bridgeData,
|
|
||||||
tokenAddress,
|
tokenAddress,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
amount
|
amount,
|
||||||
|
bridgeData
|
||||||
);
|
);
|
||||||
// Unpack the bridgeData.
|
// Unpack the bridgeData.
|
||||||
(
|
(
|
||||||
|
@ -16,12 +16,13 @@ import * as _ from 'lodash';
|
|||||||
import {
|
import {
|
||||||
artifacts,
|
artifacts,
|
||||||
ERC20BridgeProxyContract,
|
ERC20BridgeProxyContract,
|
||||||
TestERC20BridgeBridgeTransferEventArgs,
|
TestERC20BridgeBridgeWithdrawToEventArgs,
|
||||||
TestERC20BridgeContract,
|
TestERC20BridgeContract,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
|
|
||||||
blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
|
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 owner: string;
|
||||||
let badCaller: string;
|
let badCaller: string;
|
||||||
let assetProxy: ERC20BridgeProxyContract;
|
let assetProxy: ERC20BridgeProxyContract;
|
||||||
@ -162,12 +163,12 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
|
|||||||
const opts = createTransferFromOpts();
|
const opts = createTransferFromOpts();
|
||||||
const logs = await transferFromAsync(opts);
|
const logs = await transferFromAsync(opts);
|
||||||
expect(logs.length).to.eq(1);
|
expect(logs.length).to.eq(1);
|
||||||
const args = logs[0].args as TestERC20BridgeBridgeTransferEventArgs;
|
const args = logs[0].args as TestERC20BridgeBridgeWithdrawToEventArgs;
|
||||||
expect(args.bridgeData).to.eq(encodeBridgeData(opts.assetData.bridgeData));
|
|
||||||
expect(args.tokenAddress).to.eq(opts.assetData.tokenAddress);
|
expect(args.tokenAddress).to.eq(opts.assetData.tokenAddress);
|
||||||
expect(args.from).to.eq(opts.from);
|
expect(args.from).to.eq(opts.from);
|
||||||
expect(args.to).to.eq(opts.to);
|
expect(args.to).to.eq(opts.to);
|
||||||
expect(args.amount).to.bignumber.eq(opts.amount);
|
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 () => {
|
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);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user