EIP-1271: Contract wallet signatures
Every signature-verifying function on the token — permit, transferWithAuthorization, receiveWithAuthorization, and cancelAuthorization — accepts signatures from smart contract wallets, not only externally owned accounts (EOAs). Contract wallet support applies on every EVM token contract except Polygon PoS, Tempo, and Hedera (see Availability). The token picks the verification path based on the signer address:
- If the signer (
owner/from/authorizer) has no code, the token verifies it as a standard Elliptic Curve Digital Signature Algorithm (ECDSA) signature throughecrecover. - If the signer is a contract, the token makes a static call to
isValidSignature(bytes32 hash, bytes signature)on it. The token accepts the signature if the call returns the EIP-1271 magic value0x1626ba7e.
Interface
The signer contract implements the following interface:
interface IERC1271 {
function isValidSignature(
bytes32 hash, bytes memory signature
) external view returns (bytes4 magicValue);
}
Gasless approvals and transfers therefore work for Safe multisigs, ERC-4337 smart accounts, and any other wallet that implements EIP-1271, with no extra integration work. For the token-side function signatures, see EIP-2612: Gasless approvals and EIP-3009: Gasless transfers.
Integration notes
Keep the following in mind when you integrate contract wallets:
- For contract wallets, use the
bytes signaturevariants — contract wallet signatures are usually not 65 bytes (for example, a Safe concatenates one signature per owner). For EOAs, pack the signature asr (32 bytes) || s (32 bytes) || v (1 byte). - Contract signatures are revocable. Unlike an ECDSA signature, the result of
isValidSignaturecan change, for example after a Safe owner rotation. An authorization that was valid when signed can therefore fail later.