Add a SafeERC20:safePermit function (#3280)
This commit is contained in:
@ -4,6 +4,7 @@ pragma solidity ^0.8.0;
|
||||
|
||||
import "../utils/Context.sol";
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../token/ERC20/extensions/draft-ERC20Permit.sol";
|
||||
import "../token/ERC20/utils/SafeERC20.sol";
|
||||
|
||||
contract ERC20ReturnFalseMock is Context {
|
||||
@ -105,6 +106,43 @@ contract ERC20NoReturnMock is Context {
|
||||
}
|
||||
}
|
||||
|
||||
contract ERC20PermitNoRevertMock is
|
||||
ERC20("ERC20PermitNoRevertMock", "ERC20PermitNoRevertMock"),
|
||||
ERC20Permit("ERC20PermitNoRevertMock")
|
||||
{
|
||||
function getChainId() external view returns (uint256) {
|
||||
return block.chainid;
|
||||
}
|
||||
|
||||
function permitThatMayRevert(
|
||||
address owner,
|
||||
address spender,
|
||||
uint256 value,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) public virtual {
|
||||
super.permit(owner, spender, value, deadline, v, r, s);
|
||||
}
|
||||
|
||||
function permit(
|
||||
address owner,
|
||||
address spender,
|
||||
uint256 value,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) public virtual override {
|
||||
try this.permitThatMayRevert(owner, spender, value, deadline, v, r, s) {
|
||||
// do nothing
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contract SafeERC20Wrapper is Context {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
@ -134,6 +172,18 @@ contract SafeERC20Wrapper is Context {
|
||||
_token.safeDecreaseAllowance(address(0), amount);
|
||||
}
|
||||
|
||||
function permit(
|
||||
address owner,
|
||||
address spender,
|
||||
uint256 value,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) public {
|
||||
SafeERC20.safePermit(IERC20Permit(address(_token)), owner, spender, value, deadline, v, r, s);
|
||||
}
|
||||
|
||||
function setAllowance(uint256 allowance_) public {
|
||||
ERC20ReturnTrueMock(address(_token)).setAllowance(allowance_);
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "../IERC20.sol";
|
||||
import "../extensions/draft-IERC20Permit.sol";
|
||||
import "../../../utils/Address.sol";
|
||||
|
||||
/**
|
||||
@ -79,6 +80,22 @@ library SafeERC20 {
|
||||
}
|
||||
}
|
||||
|
||||
function safePermit(
|
||||
IERC20Permit token,
|
||||
address owner,
|
||||
address spender,
|
||||
uint256 value,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) internal {
|
||||
uint256 nonceBefore = token.nonces(owner);
|
||||
token.permit(owner, spender, value, deadline, v, r, s);
|
||||
uint256 nonceAfter = token.nonces(owner);
|
||||
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
|
||||
* on the return value: the return value is optional (but if data is returned, it must not be false).
|
||||
|
||||
Reference in New Issue
Block a user