-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix to ExampleCombinedSwapAddRemoveLiquidity.sol: using MAX_UINT approvals with the router #38
Fix to ExampleCombinedSwapAddRemoveLiquidity.sol: using MAX_UINT approvals with the router #38
Conversation
…that don't support changing a non-zero approval
// grants unlimited approval for a token to the router unless the existing allowance is high enough | ||
function approveRouter(address _token, uint256 _amount) internal { | ||
if (IERC20(_token).allowance(address(this), address(router)) < _amount) { | ||
TransferHelper.safeApprove(_token, address(router), uint256(-1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't we have to approve(0) first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, indeed. I had assumed that tokens that forbid calling approve()
with a non-zero amount when the existing allowance is non-zero would skip the allowance update in transferFrom()
when the allowance is MAX_UINT (as is the case for USDT) but thinking about this more, I see no reason to make this assumption. Will fix.
…owance has shrank to less than the required amount
@@ -53,7 +53,7 @@ describe('ExampleCombinedSwapAddRemoveLiquidity', () => { | |||
await wethPair.mint(wallet.address, overrides) | |||
} | |||
|
|||
beforeEach(async function() { | |||
beforeEach(async function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prob causing a linter issue
code change lgtm, i don't see any way this could cause a security issue, could use a test but this is use-at-your-own-risk code, happy to merge this once you fix the linter error so the tests pass |
Some tokens like USDT do not allow approving an amount M > 0 when an existing amount N > 0 is already approved. This is to protect from an ERC20 attack vector described here https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#heading=h.b32yfk54vyg9.
ExampleCombinedSwapAddRemoveLiquidity approves UniswapV2Router to pull some tokens from itself but UniswapV2Router does not always use its full allowance and sometimes leaves some residual allowance after the transaction. As a result, the next time ExampleCombinedSwapAddRemoveLiquidity tries to approve UniswapV2Router, the residual allowance makes the approval fail for tokens such as USDT.
This PR resolves this issue by approving the router to transfer MAX_UINT tokens from ExampleCombinedSwapAddRemoveLiquidity.