Smart contract wallet signed messages can become stale, meaning a signature that once was valid could become invalid at any point.

Signatures MAY become stale for reasons like:

  • The internal set of signers changed
  • The wallet makes signatures expirable
  • The contract was updated to a new implementation

The following standard allows smart contract wallets to expose a URI that clients can use to replace a stale signature with a valid one.


In contrast to EOA signatures, EIP-1271 signatures are not necessarily idempotent; they can become invalid at any point in time. This poses a challenge to protocols that rely on signatures remaining valid for extended periods of time.

A signature MAY need to be mutated due to one of the following scenarios:

  1. The wallet removes a signer that contributed to signing the initial message.
  2. The wallet uses a Merkle tree to store signers, adding a new signer.
  3. The wallet uses a Merkle tree to store signatures, adding new signatures.
  4. The wallet is updated to a new implementation, and the signature schema changes.

Non-interactive signature replacement SHOULD be possible, since the wallet that originally signed the message MAY NOT be available when the signature needs to be validated. An example use-case is the settlement of a trade in an exchange that uses an off-chain order book.


The wallet contract MUST implement the following function:

function getAlternativeSignature(bytes32 _digest) external view returns (string);

The returned string MUST be a URI pointing to a JSON object with the following schema:

    "title": "Signature alternative",
    "type": "object",
    "properties": {
        "blockHash": {
            "type": "string",
            "description": "A block.hash on which the signature should be valid."
        "signature": {
            "type": "string",
            "description": "The alternative signature for the given digest."

Client process for replacing a signature

A client is an entity that holds a signature and intends to validate it, either for off-chain or on-chain use. To use the smart contract wallet signature, the client MUST perform the following actions:

1) Try validating the signature using EIP-1271; if the signature is valid, then the signature can be used as-is. 2) If the signature is not valid, call getAlternativeSignature(_digest), passing the digest corresponding to the old signature. 3) If the call fails, no URI is returned, or the content of the URI is not valid, then the signature MUST be considered invalid. 4) Try validating the new signature using EIP-1271; if the signature is valid, it can be used as a drop-in replacement of the original signature. 5) If the validation fails, repeat the process from step (2) (notice: if the URI returns the same signature, the signature MUST be considered invalid).

Clients MUST implement a retry limit when fetching alternative signatures. This limit is up to the client to define.


A URI is chosen because it can accommodate centralized and decentralized solutions. For example, a server can implement live re-encoding for Merkle proofs, or an IPFS link could point to a directory with all the pre-computed signature mutations.

The getAlternativeSignature method points to an off-chain source because it’s expected that the smart contract wallet doesn’t contain on-chain records for all signed digests, if that were the case then such contract wouldn’t need to use this EIP since it could directly validate the digest onisValidSignature ignoring the stale signature.

Backwards Compatibility

Existing wallets that do not implement the getAlternativeSignature method can still sign messages without any changes; if any signatures become invalidated, clients will drop them on step (3).

Security Considerations

Some applications use signatures as secrets; these applications would risk leaking such secrets if the EIP exposes the signatures.

Copyright and related rights waived via CC0.