-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Add a safePermit function for ensuring reverting calls to ERC20.permit() #3145
Comments
Thanks for sharing the idea @hjorthjort. I think it makes sense to have a It's worth noting that if permit is a phantom function then |
I think it's a good protective measure to call nonces (if // Note: Pseudo-code
function safePermit( ... ) {
(success, data) = token.call(permit's hash, owner, spender, value, deadline, v, r, s);
if (data.length == 0) {
// compatibility mode
// double check whether the token actually implements ERC-2612's `nonces` function.
token.nonces(owner); // The return value is intentionally ignored.
}
else {
// If "permit()" call returns a bool value, we can avoid making another external call.
require( abi.decode(data, (bool)), ...); // check the return value.
}
} |
Thanks for the suggestion. I think it's unlikely to expect the I'm not a big fan of the "if the call succeeds then the function is implemented" approach. It is generally not safe to assume a function will revert if it is not specifically implemented. Relying on contracts to not return any value for specific calls (instead of checking their semantic specification) feels like kicking the can down the road. But, I know this approach is used in In the case of EIP-2612 we have a simple measure in the fact that the semantics of nonces are extremely clear. In EIP-20 there is plenty of room for interpretation on how the contract should be updated. I think that since here we have a way to be more safe at a small gas cost, we should. |
I wonder why you would check the nonce (needs two read) rather than checking the allowance (only one read needed). After all, I'm not sure we care about the nonce behavior (might work differently) as long as the approval is set correctly, right? |
Checking allowance is not enough to verify that a permit was used successfully, because the allowance may just happen to be the same value contained in the permit. |
🧐 Motivation
The Multichain/AnySwap exploits were caused by smart contracts incorrectly assuming that a failed
permit
call would always revert. This is similar to how a smart contract might assume that calls totransfer
orapprove
will revert if they fail. For this, OpenZeppelin'sSafeERC20
library has thesafeTransfer
,safeTransferFrom
,safeApprove
, etc.📝 Details
ERC2612
permit
functions do not return any value to indicate success, they only revert. However, a "phantom function" call behaves exactly like a successful call, unless state is inspected.ERC2612 tokens maintain and expose a mapping of nonces, and a successful call to
permit
MUST increment the nonce of the owner address. This state update can be observed to ensure that a permit function has successfully been called.The suggested file for this would be
contracts/token/ERC20/utils/SafeERC20Permit.sol
.The text was updated successfully, but these errors were encountered: