{"id":"ERC-1271","name":"Standard Signature Validation for Contracts","status":"Final","chain":"both","category":{"id":"security","name":"Security & Trust","description":"Helping users verify, control, and protect their assets"},"journeyStages":[{"id":"authentication","name":"Authentication & Identity","description":"Proving who you are and logging in"}],"uxImpact":"ERC-1271 lets a contract account validate a signature through isValidSignature. It broadens signature verification for protocols that explicitly accept contract signatures; it does not change an ERC-2612 token's required ECDSA permit path or guarantee that every marketplace accepts contract accounts.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-1271","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-1271","summary":"ERC-1271 lets a contract account validate a signature through isValidSignature. It broadens signature verification for protocols that explicitly accept contract signatures; it does not change an ERC-2612 token's required ECDSA permit path or guarantee that every marketplace accepts contract accounts.","applicability":{"whenToUse":["The consuming login, marketplace, or authorization protocol explicitly accepts ERC-1271 contract signatures.","The verifier can check deployed contract accounts and, when in scope, ERC-6492 counterfactual wrappers.","The flow can show asynchronous or unavailable verification states."],"whenToAvoid":["The consuming protocol only accepts EOA ECDSA signatures.","The verifier cannot check ERC-6492 wrappers for undeployed accounts when those are in scope.","The app needs immediate synchronous verification but the contract may require an asynchronous call."]},"designerTakeaways":["You can show which consuming protocol accepts contract signatures and which path is available.","You can support deployed ERC-1271 wallets and ERC-6492 wrappers for counterfactual accounts when the verifier does.","You can surface asynchronous verification and the actual verification state instead of assuming code means EOA or contract."],"problemsSolved":[{"problem":"Smart wallets can't sign messages for login","oldWay":"A verifier that accepts only EOA signatures can exclude contract accounts; EOAs do not necessarily use seed-phrase onboarding.","newWay":"Any contract can implement isValidSignature() to verify signatures","impact":"critical"},{"problem":"Multisig users locked out of dApps","oldWay":"A login or order verifier using only EOA recovery can reject a multisig account.","newWay":"A compatible consumer can validate the multisig account's ERC-1271 result; signature collection remains account-specific.","impact":"critical"},{"problem":"Permit/gasless approvals don't work for smart wallets","oldWay":"ERC-2612 permit only worked with EOA ECDSA signatures","newWay":"A token, marketplace, or other consuming protocol can add an ERC-1271 path if its own authorization flow supports contract signatures","impact":"high"},{"problem":"Off-chain order signing excludes smart wallet users","oldWay":"An order protocol accepts only EOA signatures.","newWay":"An integrated protocol can accept contract accounts by checking isValidSignature.","impact":"high"},{"problem":"Each smart wallet has different signature validation","oldWay":"Every multisig had its own signature scheme, apps couldn't support all","newWay":"A consuming protocol can use one ERC-1271 verification path for wallets that implement it, with capability and account-type handling","impact":"medium"}],"uxPatterns":[{"name":"Smart Wallet Login","description":"Sign-in flow that works for both EOAs and smart wallets","userFlow":["User connects smart wallet","App identifies the verification paths in scope, including counterfactual wrapper support","Shows the relevant signing and verification state for an EOA, deployed contract, or counterfactual account","User initiates signature request","Other signers approve if needed","App verifies via isValidSignature()","User logged in"]},{"name":"Multisig Signature Progress","description":"Optional signature collection UI for an integration that exposes a multisig threshold and signer progress. ERC-1271 alone provides neither.","userFlow":["Confirm that this account integration exposes signer identities, threshold, and collection status","Signature request created","First signer signs","Progress updates in real-time","Second signer notified","Threshold reached","Signature validated, action proceeds"]},{"name":"Contract-signed marketplace order","description":"An order flow for a marketplace that explicitly accepts ERC-1271 signatures. Token approval, relaying, and fees remain separate integration requirements.","userFlow":["User fills listing details","App checks wallet type","App checks whether the marketplace and token authorization path accept contract signatures","User signs listing order","Smart wallet validates via 1271","Listing goes live through the marketplace's supported relaying or on-chain approval path."]},{"name":"Integration-aware signature verification","description":"Detect wallet type and verify appropriately","userFlow":["App receives a signature from an unknown account","Check for an ERC-6492 wrapper when counterfactual accounts are in scope","For a deployed contract account, call isValidSignature()","For an EOA path, recover and compare the signer","Confirm the consuming protocol accepts the verified account type","Display the actual verification result and state"]}],"uiComponents":[{"name":"WalletTypeIndicator","description":"Show whether connected wallet is EOA or smart wallet","states":["eoa","smart-wallet","multisig","unknown"],"props":["walletAddress","walletType","walletName","threshold"]},{"name":"SignatureProgress","description":"Optional collection progress when the wallet integration exposes a multisig threshold and signer state.","states":["pending","partial","complete","expired"],"props":["collected","required","signers[]","deadline"]},{"name":"SmartWalletBadge","description":"Indicate smart wallet compatibility","states":["compatible","incompatible","checking"],"props":["walletType","supportedFeatures[]"]},{"name":"SignerList","description":"Optional list of known signers from an account-specific integration.","states":["waiting","signed","rejected"],"props":["signers[]","signedBy[]","requiredCount"]},{"name":"AccountSignButton","description":"Sign button that adapts to wallet type","states":["ready","awaiting-signatures","complete","error"],"props":["message","walletType","onSign","signaturesNeeded"]}],"antiPatterns":[{"pattern":"Assuming all wallets are EOAs","why":"Smart wallet users get \"invalid signature\" errors and can't use your app","instead":"Check ERC-6492 wrappers when supported, then deployed contract code and ERC-1271, then the EOA recovery path.","severity":"critical"},{"pattern":"Only using ecrecover for signature validation","why":"EOA recovery alone cannot validate a contract account's own authorization policy.","instead":"Use the verifier order supported by the integration: ERC-6492 wrapper, deployed ERC-1271, then EOA recovery.","severity":"critical"},{"pattern":"Hiding progress in an integration with a verified multisig workflow","why":"Users don't know if their request is pending or failed","instead":"If the wallet exposes a signer threshold and collection state, display that progress. Otherwise show signature verification pending without inventing a signer count.","severity":"high"},{"pattern":"Hiding wallet type from users","why":"Smart wallet users don't know why signing flow is different","instead":"Show contract-signature verification by default. Use Multisig and signer counts only when the account integration confirms those capabilities.","severity":"high"},{"pattern":"Short signature timeouts for multisigs","why":"Multisigs need time to collect signatures from multiple parties","instead":"Allow longer validity periods or refreshable signatures","severity":"medium"},{"pattern":"Not providing reminder/notification for pending signatures","why":"Signatures stall because other signers don't know they're needed","instead":"Offer reminders only through an explicitly supported account integration, with user-controlled recipients and delivery.","severity":"medium"}],"specConstraints":[{"id":"signature-validity-result","constraint":"isValidSignature must return the ERC-1271 magic value when the signature passes.","appliesTo":"application","normativity":"normative","specQuote":"* MUST return the bytes4 magic value 0x1626ba7e when function passes.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1271#specification","designImplication":"Show the consuming protocol’s accepted/invalid contract-signature result and do not infer validity merely from contract ownership."},{"id":"contract-signature-implementation","constraint":"Contracts that desire to sign messages SHOULD implement ERC-1271's isValidSignature method.","appliesTo":"account-implementation","normativity":"normative","specQuote":"This function should be implemented by contracts which desire to sign messages (e.g. smart contract wallets, DAOs, multisignature wallets, etc.)","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1271#specification","designImplication":"When an account integration offers contract-based signing, expose the ERC-1271 verification path and distinguish it from EOA recovery."},{"id":"contract-signature-caller-path","constraint":"Applications supporting contract signatures SHOULD call isValidSignature when the signer is a contract.","appliesTo":"application","normativity":"normative","specQuote":"Applications wanting to support contract signatures should call this method if the signer is a contract.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1271#specification","designImplication":"Detect contract signers before validation and route them to ERC-1271, with an explicit unsupported or pending state when the consuming protocol does not support contract signatures."},{"id":"offchain-signature-check","constraint":"The signature-check method is intended to be state-free and usable for offchain contract queries.","appliesTo":"application","normativity":"rationale","specQuote":"`isValidSignature()` should not be able to modify states in order to prevent `GasToken` minting or similar attack vectors. Again, this is to simplify the implementation surface of the function for better standardization and to allow off-chain contract queries.","specSection":"Rationale","specUrl":"https://ercs.ethereum.org/ERCS/erc-1271#rationale","designImplication":"Support asynchronous read-only verification states and avoid presenting a pending contract-signature check as a completed authorization."},{"id":"contract-signature-compat","constraint":"Contract-based signature validation is compatible with prior signature-validation work without changing EOA signatures.","appliesTo":"application","normativity":"backwards-compatibility","specQuote":"## Backwards Compatibility\n\nThis EIP is backward compatible with previous work on signature validation since this method is specific to contract based signatures and not EOA signatures.","specSection":"Backwards Compatibility","specUrl":"https://ercs.ethereum.org/ERCS/erc-1271#backwards-compatibility","designImplication":"Keep EOA and contract-account verification paths explicit and only offer ERC-1271 where the consuming protocol supports it."},{"id":"contract-signature-security","constraint":"Callers should not hardcode a gas limit for isValidSignature, and each implementing contract is responsible for validating signatures correctly.","appliesTo":"application","normativity":"security-considerations","specQuote":"## Security Considerations\nSince there are no gas-limit expected for calling the isValidSignature() function, it is possible that some implementation will consume a large amount of gas. It is therefore important to not hardcode an amount of gas sent when calling this method on an external contract as it could prevent the validation of certain signatures.\n\nNote also that each contract implementing this method is responsible to ensure that the signature passed is indeed valid, otherwise catastrophic outcomes are to be expected.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-1271#security-considerations","designImplication":"Show verifier identity and actual validation status, allow for variable verification cost, and treat an invalid contract implementation as a critical trust failure."}],"keyTakeaways":["ERC-1271 lets deployed contract accounts validate signatures.","The consuming token, marketplace, or login protocol must support the contract path.","Check ERC-6492 wrappers before treating a no-code address as an EOA when counterfactual accounts are in scope.","Show asynchronous and pending verification states.","Do not infer a universal permit or marketplace integration from ERC-1271 alone."],"technicalNotes":"ERC-1271 defines isValidSignature(bytes32 hash, bytes signature) returning the magic value 0x1626ba7e when valid. A deployed contract account can validate through this function, but a no-code address is not automatically an EOA: counterfactual accounts may use ERC-6492 wrappers before deployment. Check ERC-6492 wrappers first when supported, then deployed ERC-1271, then the EOA path. The consuming protocol must explicitly accept the contract-signature path. Validation can change with account state or time; recheck at the point of use rather than treating a previous valid result as permanent.","lastUpdated":"2026-09-18","sources":[{"label":"ERC-1271 official specification","url":"https://ercs.ethereum.org/ERCS/erc-1271","type":"official-spec"}],"lastReviewed":"2026-09-18"},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-1271","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-1271","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-1271","markdown":"https://www.eipsfordesigners.com/standards/ERC-1271/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-1271/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-1271","official":"https://ercs.ethereum.org/ERCS/erc-1271","discussion":"https://ethereum-magicians.org/search?q=ERC-1271"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}