@0x/contracts-erc20: Add LibERC20Token.approveIfBelowMax().

`@0x/contracts-asset-proxy`: Use `LibERC20Token.approveIfBelowMax` in all DEX bridges.
This commit is contained in:
Lawrence Forman 2020-03-04 14:49:40 -05:00
parent bcd92473d1
commit b604e2bd4e
10 changed files with 49 additions and 4 deletions

View File

@ -1,4 +1,12 @@
[
{
"version": "3.3.0",
"changes": [
{
"note": "Use `approveIfBelowMax()` in DEX bridges for for approvals."
}
]
},
{
"timestamp": 1583220306,
"version": "3.2.5",

View File

@ -61,7 +61,7 @@ contract CurveBridge is
address fromTokenAddress = exchange.underlying_coins(fromCoinIdx);
require(toTokenAddress != fromTokenAddress, "CurveBridge/INVALID_PAIR");
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1));
LibERC20Token.approveIfBelowMax(fromTokenAddress, address(exchange));
// Try to sell all of this contract's `fromTokenAddress` token balance.
if (version == 0) {

View File

@ -57,7 +57,7 @@ contract Eth2DaiBridge is
IEth2Dai exchange = IEth2Dai(_getEth2DaiAddress());
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1));
LibERC20Token.approveIfBelowMax(fromTokenAddress, address(exchange));
// Try to sell all of this contract's `fromTokenAddress` token balance.
uint256 boughtAmount = exchange.sellAllAmount(

View File

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

View File

@ -168,7 +168,7 @@ contract UniswapBridge is
function _grantExchangeAllowance(IUniswapExchange exchange, address tokenAddress)
private
{
LibERC20Token.approve(tokenAddress, address(exchange), uint256(-1));
LibERC20Token.approveIfBelowMax(tokenAddress, address(exchange));
}
/// @dev Retrieves the uniswap exchange for a given token pair.

View File

@ -110,6 +110,10 @@ contract TestToken {
return true;
}
function allowance(address, address) external view returns (uint256) {
return 0;
}
/// @dev Retrieve the balance for `owner`.
function balanceOf(address owner)
external

View File

@ -110,6 +110,10 @@ contract TestToken {
return _testContract.wethDeposit.value(msg.value)(msg.sender);
}
function allowance(address, address) external view returns (uint256) {
return 0;
}
function balanceOf(address owner)
external
view

View File

@ -224,6 +224,10 @@ contract TestToken {
TestEventsRaiser(msg.sender).raiseWethWithdraw(amount);
}
function allowance(address, address) external view returns (uint256) {
return 0;
}
/// @dev Retrieve the balance for `owner`.
function balanceOf(address owner)
external

View File

@ -1,4 +1,12 @@
[
{
"version": "3.2.0",
"changes": [
{
"note": "Add `LibERC20Token.approveIfBelowMax()`"
}
]
},
{
"timestamp": 1583220306,
"version": "3.1.5",

View File

@ -47,6 +47,23 @@ library LibERC20Token {
_callWithOptionalBooleanResult(token, callData);
}
/// @dev Calls `IERC20Token(token).approve()` and sets the allowance to the
/// maximum if the current approval is not already set to the maximum.
/// Reverts if `false` is returned or if the return
/// data length is nonzero and not 32 bytes.
/// @param token The address of the token contract.
/// @param spender The address that receives an allowance.
function approveIfBelowMax(
address token,
address spender
)
internal
{
if (IERC20Token(token).allowance(address(this), spender) != uint256(-1)) {
approve(token, spender, uint256(-1));
}
}
/// @dev Calls `IERC20Token(token).transfer()`.
/// Reverts if `false` is returned or if the return
/// data length is nonzero and not 32 bytes.