@0x/contracts-asset-proxy
: Use LibERC20Token
in UniswapBridge
and Eth2DaiBridge
.
This commit is contained in:
parent
c8ef10baaf
commit
0f3610c92a
@ -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) });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user