@0x/contracts-erc20: Switch LibERC20Token.approveIfBelowMax() to LibERC20Token.approveIfBelow().

`@0x/contracts-asset-proxy`: Use `LibERC20Token.approveIfBelow()` for bridge approvals.
This commit is contained in:
Lawrence Forman 2020-03-04 21:32:47 -05:00
parent 3f51b9322f
commit c3d4c13936
7 changed files with 30 additions and 16 deletions

View File

@ -3,7 +3,7 @@
"version": "3.3.0", "version": "3.3.0",
"changes": [ "changes": [
{ {
"note": "Use `approveIfBelowMax()` in DEX bridges for for approvals.", "note": "Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals.",
"pr": 2512 "pr": 2512
}, },
{ {

View File

@ -67,9 +67,9 @@ contract CurveBridge is
address fromTokenAddress = ICurve(data.curveAddress).underlying_coins(data.fromCoinIdx); address fromTokenAddress = ICurve(data.curveAddress).underlying_coins(data.fromCoinIdx);
require(toTokenAddress != fromTokenAddress, "CurveBridge/INVALID_PAIR"); require(toTokenAddress != fromTokenAddress, "CurveBridge/INVALID_PAIR");
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelowMax(fromTokenAddress, data.curveAddress);
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelow(fromTokenAddress, data.curveAddress, fromTokenBalance);
// Try to sell all of this contract's `fromTokenAddress` token balance. // Try to sell all of this contract's `fromTokenAddress` token balance.
if (data.version == 0) { if (data.version == 0) {

View File

@ -57,10 +57,9 @@ contract Eth2DaiBridge is
(address fromTokenAddress) = abi.decode(bridgeData, (address)); (address fromTokenAddress) = abi.decode(bridgeData, (address));
IEth2Dai exchange = IEth2Dai(_getEth2DaiAddress()); IEth2Dai exchange = IEth2Dai(_getEth2DaiAddress());
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelowMax(fromTokenAddress, address(exchange));
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance);
// Try to sell all of this contract's `fromTokenAddress` token balance. // Try to sell all of this contract's `fromTokenAddress` token balance.
uint256 boughtAmount = exchange.sellAllAmount( uint256 boughtAmount = exchange.sellAllAmount(

View File

@ -110,7 +110,11 @@ contract KyberBridge is
} else if (state.fromTokenAddress != address(state.weth)) { } else if (state.fromTokenAddress != address(state.weth)) {
// If the input token is not WETH, grant an allowance to the exchange // If the input token is not WETH, grant an allowance to the exchange
// to spend them. // to spend them.
LibERC20Token.approveIfBelowMax(state.fromTokenAddress, address(state.kyber)); LibERC20Token.approveIfBelow(
state.fromTokenAddress,
address(state.kyber),
state.fromTokenBalance
);
} else { } else {
// If the input token is WETH, unwrap it and attach it to the call. // If the input token is WETH, unwrap it and attach it to the call.
state.fromTokenAddress = KYBER_ETH_ADDRESS; state.fromTokenAddress = KYBER_ETH_ADDRESS;

View File

@ -110,7 +110,7 @@ contract UniswapBridge is
// Convert from a token to WETH. // Convert from a token to WETH.
} else if (toTokenAddress == address(state.weth)) { } else if (toTokenAddress == address(state.weth)) {
// Grant the exchange an allowance. // Grant the exchange an allowance.
_grantExchangeAllowance(state.exchange, fromTokenAddress); _grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
// Buy as much ETH with `fromTokenAddress` token as possible. // Buy as much ETH with `fromTokenAddress` token as possible.
state.boughtAmount = state.exchange.tokenToEthSwapInput( state.boughtAmount = state.exchange.tokenToEthSwapInput(
// Sell all tokens we hold. // Sell all tokens we hold.
@ -128,7 +128,7 @@ contract UniswapBridge is
// Convert from one token to another. // Convert from one token to another.
} else { } else {
// Grant the exchange an allowance. // Grant the exchange an allowance.
_grantExchangeAllowance(state.exchange, fromTokenAddress); _grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
// Buy as much `toTokenAddress` token with `fromTokenAddress` token // Buy as much `toTokenAddress` token with `fromTokenAddress` token
// and transfer it to `to`. // and transfer it to `to`.
state.boughtAmount = state.exchange.tokenToTokenTransferInput( state.boughtAmount = state.exchange.tokenToTokenTransferInput(
@ -177,10 +177,19 @@ contract UniswapBridge is
/// on behalf of this contract. /// on behalf of this contract.
/// @param exchange The Uniswap token exchange. /// @param exchange The Uniswap token exchange.
/// @param tokenAddress The token address for the exchange. /// @param tokenAddress The token address for the exchange.
function _grantExchangeAllowance(IUniswapExchange exchange, address tokenAddress) /// @param minimumAllowance The minimum necessary allowance.
function _grantExchangeAllowance(
IUniswapExchange exchange,
address tokenAddress,
uint256 minimumAllowance
)
private private
{ {
LibERC20Token.approveIfBelowMax(tokenAddress, address(exchange)); LibERC20Token.approveIfBelow(
tokenAddress,
address(exchange),
minimumAllowance
);
} }
/// @dev Retrieves the uniswap exchange for a given token pair. /// @dev Retrieves the uniswap exchange for a given token pair.

View File

@ -3,7 +3,7 @@
"version": "3.2.0", "version": "3.2.0",
"changes": [ "changes": [
{ {
"note": "Add `LibERC20Token.approveIfBelowMax()`", "note": "Add `LibERC20Token.approveIfBelow()`",
"pr": 2512 "pr": 2512
} }
] ]

View File

@ -48,18 +48,20 @@ library LibERC20Token {
} }
/// @dev Calls `IERC20Token(token).approve()` and sets the allowance to the /// @dev Calls `IERC20Token(token).approve()` and sets the allowance to the
/// maximum if the current approval is not already set to the maximum. /// maximum if the current approval is not already >= an amount.
/// Reverts if `false` is returned or if the return /// Reverts if `false` is returned or if the return
/// data length is nonzero and not 32 bytes. /// data length is nonzero and not 32 bytes.
/// @param token The address of the token contract. /// @param token The address of the token contract.
/// @param spender The address that receives an allowance. /// @param spender The address that receives an allowance.
function approveIfBelowMax( /// @param amount The minimum allowance needed.
function approveIfBelow(
address token, address token,
address spender address spender,
uint256 amount
) )
internal internal
{ {
if (IERC20Token(token).allowance(address(this), spender) != uint256(-1)) { if (IERC20Token(token).allowance(address(this), spender) < amount) {
approve(token, spender, uint256(-1)); approve(token, spender, uint256(-1));
} }
} }