RFC: Using this.balance
as a Storage-Free Deactivation Mechanism Post-Cancun
After the Cancun upgrade and the changes introduced by EIP-6780, the ability to deactivate and reactivate a contract dynamically has become more challenging, particularly in scenarios where querying storage for every transaction is not desirable. I am proposing a minimalistic mechanism for activating and deactivating a contract (specifically a router contract) using the built-in this.balance
variable as a control flag.
Use Case
The router contract in question:
- Holds user approvals but no tokens or significant business logic.
- Does not hold ETH in its normal operation.
- Needs a reliable, storage-free way to toggle between an active and inactive state.
This is particularly useful in cases where:
- A bug is identified in the contract, and users need to be prevented from interacting with it until it is fixed.
- There’s a need to deactivate the router swiftly without requiring manual revocation of user approvals.
Proposed Mechanism
The mechanism relies solely on the contract’s ETH balance (this.balance
) to toggle its state. The logic is as follows:
- State Definition:
- Deactivated:
this.balance == 0
. The contract rejects all interactions. - Activated:
this.balance == 1 wei
. The contract functions normally.
- State Transitions:
- Activate the Contract: The
activate()
function (restricted to an immutable DEACTIVATOR address) sends 1 wei to the contract, setting it to an active state. - Deactivate the Contract: The
deactivate()
function (also restricted) transfers all ETH in the contract back to the DEACTIVATOR, setting the balance to zero.
- Key Features:
- The router has no
receive
function, ensuring that ETH cannot be accidentally or maliciously sent to it. - All state transitions rely exclusively on the ETH balance, eliminating the need to query or store custom state variables.
Benefits
- No Storage Reads: State checking relies on
this.balance
, avoiding the gas cost of reading from storage. - Efficient State Transitions: Activating or deactivating involves only minimal ETH transfers.
- Safety: The absence of a
receive
function ensures the router cannot accidentally accumulate ETH.
Why This Is Useful
This mechanism provides a lightweight way to handle router deactivation, especially in scenarios where:
- Bugs in router contracts force users to manually revoke approvals.
- State querying for every transaction is undesirable due to gas costs or complexity.
Using the contract’s ETH balance as a toggle avoids the need for storage variables while enabling quick and efficient state changes. This approach could benefit other contract designs requiring similar activation/deactivation mechanisms in a storage-free context.