@0x/contracts-asset-proxy: Use LibERC20Token in UniswapBridge and Eth2DaiBridge.
				
					
				
			This commit is contained in:
		| @@ -21,6 +21,7 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
| import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/LibERC20Token.sol"; | ||||
| import "../interfaces/IERC20Bridge.sol"; | ||||
| import "../interfaces/IEth2Dai.sol"; | ||||
|  | ||||
| @@ -57,7 +58,7 @@ contract Eth2DaiBridge is | ||||
|  | ||||
|         IEth2Dai exchange = _getEth2DaiContract(); | ||||
|         // Grant an allowance to the exchange to spend `fromTokenAddress` token. | ||||
|         IERC20Token(fromTokenAddress).approve(address(exchange), uint256(-1)); | ||||
|         LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1)); | ||||
|  | ||||
|         // Try to sell all of this contract's `fromTokenAddress` token balance. | ||||
|         uint256 boughtAmount = _getEth2DaiContract().sellAllAmount( | ||||
| @@ -67,7 +68,7 @@ contract Eth2DaiBridge is | ||||
|             amount | ||||
|         ); | ||||
|         // Transfer the converted `toToken`s to `to`. | ||||
|         _transferERC20Token(toTokenAddress, to, boughtAmount); | ||||
|         LibERC20Token.transfer(toTokenAddress, to, boughtAmount); | ||||
|         return BRIDGE_SUCCESS; | ||||
|     } | ||||
|  | ||||
| @@ -94,49 +95,4 @@ contract Eth2DaiBridge is | ||||
|     { | ||||
|         return IEth2Dai(ETH2DAI_ADDRESS); | ||||
|     } | ||||
|  | ||||
|     /// @dev Permissively transfers an ERC20 token that may not adhere to | ||||
|     ///      specs. | ||||
|     /// @param tokenAddress The token contract address. | ||||
|     /// @param to The token recipient. | ||||
|     /// @param amount The amount of tokens to transfer. | ||||
|     function _transferERC20Token( | ||||
|         address tokenAddress, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         private | ||||
|     { | ||||
|         // Transfer tokens. | ||||
|         // We do a raw call so we can check the success separate | ||||
|         // from the return data. | ||||
|         (bool didSucceed, bytes memory returnData) = tokenAddress.call( | ||||
|             abi.encodeWithSelector( | ||||
|                 IERC20Token(0).transfer.selector, | ||||
|                 to, | ||||
|                 amount | ||||
|             ) | ||||
|         ); | ||||
|         if (!didSucceed) { | ||||
|             assembly { revert(add(returnData, 0x20), mload(returnData)) } | ||||
|         } | ||||
|  | ||||
|         // Check return data. | ||||
|         // If there is no return data, we assume the token incorrectly | ||||
|         // does not return a bool. In this case we expect it to revert | ||||
|         // on failure, which was handled above. | ||||
|         // If the token does return data, we require that it is a single | ||||
|         // value that evaluates to true. | ||||
|         assembly { | ||||
|             if returndatasize { | ||||
|                 didSucceed := 0 | ||||
|                 if eq(returndatasize, 32) { | ||||
|                     // First 64 bytes of memory are reserved scratch space | ||||
|                     returndatacopy(0, 0, 32) | ||||
|                     didSucceed := mload(0) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         require(didSucceed, "ERC20_TRANSFER_FAILED"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2; | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol"; | ||||
| import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/LibERC20Token.sol"; | ||||
| import "../interfaces/IUniswapExchangeFactory.sol"; | ||||
| import "../interfaces/IUniswapExchange.sol"; | ||||
| import "../interfaces/IERC20Bridge.sol"; | ||||
| @@ -77,7 +78,7 @@ contract UniswapBridge is | ||||
|  | ||||
|         // Just transfer the tokens if they're the same. | ||||
|         if (fromTokenAddress == toTokenAddress) { | ||||
|             IERC20Token(fromTokenAddress).transfer(to, amount); | ||||
|             LibERC20Token.transfer(fromTokenAddress, to, amount); | ||||
|             return BRIDGE_SUCCESS; | ||||
|         } | ||||
|  | ||||
| @@ -189,7 +190,7 @@ contract UniswapBridge is | ||||
|     function _grantExchangeAllowance(IUniswapExchange exchange, address tokenAddress) | ||||
|         private | ||||
|     { | ||||
|         IERC20Token(tokenAddress).approve(address(exchange), uint256(-1)); | ||||
|         LibERC20Token.approve(tokenAddress, address(exchange), uint256(-1)); | ||||
|     } | ||||
|  | ||||
|     /// @dev Retrieves the uniswap exchange for a given token pair. | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import { | ||||
|     TransactionHelper, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { AssetProxyId } from '@0x/types'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
| import { BigNumber, RawRevertError } from '@0x/utils'; | ||||
| import { DecodedLogs } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| @@ -179,14 +179,14 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => { | ||||
|             return expect(tx).to.revertWith(opts.toTokentransferRevertReason); | ||||
|         }); | ||||
|  | ||||
|         it('fails if `toTokenAddress.transfer()` returns falsey', async () => { | ||||
|         it('fails if `toTokenAddress.transfer()` returns false', async () => { | ||||
|             const opts = createWithdrawToOpts({ toTokenTransferReturnData: hexLeftPad(0) }); | ||||
|             const tx = withdrawToAsync(opts); | ||||
|             return expect(tx).to.revertWith('ERC20_TRANSFER_FAILED'); | ||||
|             return expect(tx).to.revertWith(new RawRevertError(hexLeftPad(0))); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds if `toTokenAddress.transfer()` returns truthy', async () => { | ||||
|             await withdrawToAsync({ toTokenTransferReturnData: hexLeftPad(100) }); | ||||
|         it('succeeds if `toTokenAddress.transfer()` returns true', async () => { | ||||
|             await withdrawToAsync({ toTokenTransferReturnData: hexLeftPad(1) }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user