From 7762b7b665e798cf6b9461523e2877e8670e0e35 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sat, 28 Sep 2019 01:54:09 -0400 Subject: [PATCH] `@0x/contracts-asset-proxy`: Add signature validation. --- contracts/asset-proxy/CHANGELOG.json | 2 +- .../contracts/src/bridges/Eth2DaiBridge.sol | 28 +++++++++++++++++-- contracts/asset-proxy/test/eth2dai_bridge.ts | 11 +++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index 344060b59c..65526c41c3 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -24,7 +24,7 @@ }, { "note": "Add `Eth2DaiBridge`", - "pr": "TODO" + "pr": 2221 } ] }, diff --git a/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol b/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol index 46cffb9c3c..ab56e1bf66 100644 --- a/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol @@ -20,13 +20,17 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; +import "@0x/contracts-exchange/contracts/src/interfaces/IWallet.sol"; import "./ERC20Bridge.sol"; import "../interfaces/IEth2Dai.sol"; +// solhint-disable space-after-comma contract Eth2DaiBridge is - ERC20Bridge + ERC20Bridge, + IWallet { + bytes4 private constant LEGACY_WALLET_MAGIC_VALUE = 0xb0671381; /* Mainnet addresses */ address constant public ETH2DAI_ADDRESS = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e; address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; @@ -38,7 +42,14 @@ contract Eth2DaiBridge is _getDaiContract().approve(address(_getEth2DaiContract()), uint256(-1)); } - // solhint-disable space-after-comma + /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of + /// `toTokenAddress` tokens by selling the entirety of the opposing asset + /// (DAI or WETH) to the Eth2Dai contract, then transfers the bought + /// tokens to `to`. + /// @param toTokenAddress The token to give to `to` (either DAI or WETH). + /// @param to The recipient of the bought tokens. + /// @param amount Minimum amount of `toTokenAddress` tokens to buy. + /// @return success The magic bytes `0xb5d40d78` if successful. function transfer( bytes calldata /* bridgeData */, address toTokenAddress, @@ -73,6 +84,19 @@ contract Eth2DaiBridge is return BRIDGE_SUCCESS; } + /// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker + /// and sign for itself in orders. Always succeeds. + function isValidSignature( + bytes32, + bytes calldata + ) + external + view + returns (bytes4 magicValue) + { + return LEGACY_WALLET_MAGIC_VALUE; + } + /// @dev Overridable way to get the weth contract. function _getWethContract() internal diff --git a/contracts/asset-proxy/test/eth2dai_bridge.ts b/contracts/asset-proxy/test/eth2dai_bridge.ts index b63fb7c216..9d1cd32585 100644 --- a/contracts/asset-proxy/test/eth2dai_bridge.ts +++ b/contracts/asset-proxy/test/eth2dai_bridge.ts @@ -4,6 +4,7 @@ import { expect, filterLogsToArguments, getRandomInteger, + hexRandom, Numberish, randomAddress, TransactionHelper, @@ -20,7 +21,7 @@ import { TestEth2DaiBridgeTokenTransferEventArgs, } from '../src'; -blockchainTests.resets('Eth2DaiBridge unit tests', env => { +blockchainTests.resets.only('Eth2DaiBridge unit tests', env => { const txHelper = new TransactionHelper(env.web3Wrapper, artifacts); let testContract: TestEth2DaiBridgeContract; let daiTokenAddress: string; @@ -47,6 +48,14 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => { }); }); + describe('isValidSignature()', () => { + it('returns success bytes', async () => { + const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381'; + const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32))); + expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE); + }); + }); + describe('transfer()', () => { interface TransferOpts { toTokenAddress: string;