EIP.tools

EIP.tools

⚠️ DraftStandards Track: ERC

ERC-8343: Contract Deactivation

Interface for permanently deactivating a token contract and exposing its deactivation status

Authors
Created2026-02-12
Discussion Linkhttps://ethereum-magicians.org/t/erc-8343-contract-deactivation/29049
Requires

Markdown

https://raw.githubusercontent.com/ethereum/ERCs/re...
Pull Request#1900PR open

EIP-GPT summary

Contents
AbstractMotivationSpecificationInterfaceERC-165 SupportRequired BehaviorRationaleBackwards CompatibilityReference ImplementationSecurity ConsiderationsCopyright

Abstract

This ERC defines a minimal interface for permanently deactivating a contract and exposing that terminal state on-chain. It introduces a one-way deactivateContract() operation and a deactivated() status view so wallets, exchanges, custodians, and protocols can reliably detect that a contract is no longer active.

The proposal is motivated by regulated Real-World Asset (RWA) use cases where issuers may need to irreversibly stop token operations due to corporate actions, legal migration, or end-of-life lifecycle events. It is also useful for DeFi applications (for example lending markets or AMM pools) that need to publish a clear on-chain signal that an instance is no longer active. The interface is intentionally small and can be combined with existing token standards such as ERC-20, ERC-721, or ERC-1155. The proposal adopts ERC-165 so integrators can discover support programmatically.

Motivation

Pause mechanisms are useful for temporary incidents. They are not enough for terminal lifecycle events where the issuer must communicate that the contract is no longer meant to be reactivated.

Common examples:

  • security migration to a new contract after a legal restructuring,
  • capitalization events (e.g. merger, split, reverse split) requiring old units to be immobilized,
  • issuer decision to discontinue a ledger-based representation,
  • DeFi market shutdowns (for example lending pool or AMM pair retirement) where operators need to signal permanent inactivity.

Without a standard signal, integrations cannot distinguish:

  • a temporary pause,
  • an operational outage,
  • a permanent deactivation.

This ERC standardizes that signal.

Historically, SELFDESTRUCT was the closest thing to a terminal "this contract is gone" signal. Since EIP-6780 (deployed in the Dencun upgrade), SELFDESTRUCT no longer deletes a contract's code or storage unless it is called in the same transaction in which the contract was created; for any already-deployed contract it only transfers the remaining ether. In practice there is therefore no longer any way to destroy a deployed smart contract. A deactivated contract keeps its code and storage and remains callable forever, so the only way to communicate that it is permanently retired is an explicit, application-level status signal such as the one this ERC defines.

This ERC is primarily designed for token contracts, but it is not limited to ERC-20 semantics and can be applied to contracts implementing other asset models.

Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Interface

interface IERCDeactivation is IERC165 {
    /// @notice Emitted when the contract is permanently deactivated.
    /// @param account The address that triggered deactivation.
    event Deactivated(address indexed account);

    /// @notice Error raised when deactivation is attempted after deactivation is already final.
    error AlreadyDeactivated();

    /// @notice Permanently deactivates the contract.
    function deactivateContract() external;

    /// @notice Returns whether the contract has been deactivated.
    function deactivated() external view returns (bool isDeactivated);
}

ERC-165 Support

Implementations MUST implement ERC-165 and MUST return true from supportsInterface for:

  • 0x01ffc9a7 (IERC165)
  • 0xe9cd80b0 (IERCDeactivation)

Implementations MUST return false for supportsInterface(0xffffffff).

Required Behavior

  1. One-way state

    • deactivated() MUST return false before successful deactivation and true after successful deactivation.
    • Once deactivated() becomes true, it MUST NOT return to false in the active implementation.
    • In upgradeable proxy systems, a future implementation MAY alter behavior. This does not break interface compatibility, but changes permanence assumptions and SHOULD be clearly disclosed to integrators.
    • Implementations behind upgradeable proxies SHOULD NOT present deactivated() as an on-chain technical guarantee of irreversible finality unless upgrade authority is effectively removed.
  2. Deactivation call

    • deactivateContract() MUST set the deactivation state to true.
    • deactivateContract() MUST emit Deactivated(account).
    • deactivateContract() MUST revert with AlreadyDeactivated() if deactivation has already happened.
    • deactivateContract() MUST be access-controlled.
  3. Pause precondition

    • Implementations using a pause mechanism SHOULD require the contract to be paused before deactivateContract() succeeds.
    • If a pause precondition is used and not met, deactivateContract() MUST revert.
  4. Post-deactivation operational guarantees

    • After deactivation, holder-initiated asset movement operations MUST revert. For example:
      • ERC-20: transfer, transferFrom
      • ERC-721
      • ERC-1155
    • After deactivated() == true, all non-privileged, non-view, and non-pure holder operations MUST revert, except for the holder exit operations explicitly permitted below.
    • Holder exit exception: Implementations MAY keep holder-initiated exit operations available after deactivation so that users can retrieve their own funds from the protocol, while capital-adding operations MUST revert. For an ERC-4626 vault, this means withdraw and redeem MAY remain callable after deactivation, whereas deposit and mint MUST revert. Any exit operation kept available MUST NOT let a holder withdraw more than their own entitlement and MUST be listed in the implementation documentation as post-deactivation-enabled.
    • After deactivation, supply-changing operations intended for normal lifecycle management (for example standard mint and burn) MUST revert.
    • If the implementation includes unpause, it MUST revert when deactivated() == true.
    • Implementations MAY keep only explicitly named privileged emergency/regulatory operations (for example forcedTransfer) available after deactivation.
    • Any privileged operation that remains available after deactivation MUST be listed in the implementation documentation and clearly marked as post-deactivation-enabled.
    • Privileged operations that are not explicitly named as post-deactivation-enabled MUST revert when deactivated() == true.
  5. Observability

    • deactivated() MUST be a non-reverting view function.
    • Indexers and off-chain systems SHOULD treat Deactivated as a terminal lifecycle event for public holder operations, rather than as a guarantee that no privileged operation can ever execute.
    • This interpretation does not imply restrictions on view or pure read-only functions.
    • For upgradeable proxy deployments, integrators are RECOMMENDED to adopt a conservative default assumption that once deactivated, the contract remains permanently deactivated, unless governance documentation explicitly states otherwise.

Rationale

  • Minimalism: Two functions and one event are sufficient for broad interoperability.
  • Separation of concerns: This ERC does not mandate any access-control model, pause design, or legal workflow.
  • RWA and DeFi lifecycle signaling: The standard addresses regulated token lifecycle events and DeFi lifecycle events (such as lending/AMM retirements) with a shared, auditable "no longer active" signal.
  • Fund recovery on exit: For DeFi protocols such as ERC-4626 vaults, deactivation is often meant to wind a market down rather than trap capital. The holder exit exception lets an implementation keep withdraw/redeem open so users can recover their own funds, while closing deposit/mint so no new capital enters a contract that is being retired.
  • Compatibility with existing pause modules: The interface composes naturally with existing pause implementations where deactivation acts as a permanent terminal pause.
  • Deployment-model neutrality: Both immutable contracts and upgradeable proxies are compatible with this ERC. The interface standardizes signaling, not governance guarantees.

Backwards Compatibility

This ERC is additive and does not modify existing token standards. Existing wallets and protocols can continue using base token interfaces and optionally integrate this ERC to detect terminal deactivation status.

Reference Implementation

A reference pattern is:

  • store a boolean isDeactivated,
  • gate deactivateContract() behind authorization,
  • require paused state (if pause exists),
  • set isDeactivated = true,
  • emit Deactivated(msg.sender),
  • reject unpause and normal transfer/mint/burn flows when deactivated.

Security Considerations

  • Authorization risk: Unauthorized access to deactivateContract() creates irreversible denial of service. Use robust access control (multisig, timelock, separation of duties).
  • Proxy nuance: In upgradeable systems, deactivation may be bypassed by deploying a new implementation that changes logic. If strict permanence is required, implementations should use immutable deployments or disable upgrades (for example by irrevocably renouncing upgrade authority).
  • Integrator default for proxies: For upgradeable proxy deployments, integrators should apply a conservative trust model and treat deactivation as permanent by default, unless issuer governance documentation explicitly communicates a different policy.
  • Operational risk: Because deactivation is terminal, operators should use staged procedures (pause first, confirm terms/migration, then deactivate).
  • Integration risk: Integrators should check deactivated() before presenting token actions to users.

Copyright and related rights waived via CC0.

EIP.tools

EIP.tools

Search, read, and map Ethereum improvement proposals, ERCs, RIPs, and CAIPs from one focused interface.

Farcaster
by @apoorveth