This SIP removes the remaining cases where SELFDESTRUCT burns SIL. Accounts marked for selfdestruction still have their code, storage, and nonce cleared at transaction finalization, but any remaining balance is preserved.
Motivation
The remaining burn behavior of SELFDESTRUCT is almost completely unused, but it still forces special-case handling in SVM implementations, specifications, and tests.
After SIP-6780, SIL can still be burned only when a contract created in the same transaction executes SELFDESTRUCT, either with itself as beneficiary or in a case where the contract receives additional SIL (via CALL or via SELFDESTRUCT, potentially multiple times) later in the same transaction.
A full replay of Sila sila-mainnet from genesis to approximately block 25M found only 2 post-SilaCancun burns through this path and 0 cases of balance being burned during transaction finalization. By comparison, pre-SilaCancun history contained 54 self-burns in total. This indicates that the remaining burn behavior is rarer than the burn behavior already removed by SIP-6780, so the complete removal proposed here should affect fewer transactions than the partial removal already introduced there.
Removing the final burn cases simplifies SELFDESTRUCT semantics and avoids preserving an exotic special case that is barely used in practice.
As a consequence, this also removes the last SVM mechanism by which SIL can leave total supply.
Specification
The behavior of SELFDESTRUCT changes as follows:
When SELFDESTRUCT is executed in the same transaction as the contract was created,
and if the beneficiary address is the executing account address,
the balance of this account remains unchanged.
During transaction finalization,
all accounts marked for selfdestruction,
instead of being deleted,
are modified as follows:
nonce is reset to 0,
balance is unchanged,
code is cleared,
all storage is cleared.
Note: All other behavior of SELFDESTRUCT is unchanged.
Note: If the resulting balance is 0, the account is empty and is deleted from the state by SIP-161.
Rationale
This change removes burn behavior at its source instead of adding dedicated handling for it elsewhere.
The chosen design preserves the state-clearing effect of SELFDESTRUCT for contracts created in the same transaction. The account may still survive in the state, but only as a balance-only account. This removes the special case where SIL disappears from the state while keeping the account non-executable after transaction finalization.
Resetting the nonce to 0 ensures that a future CREATE2 at the same address is not blocked by a preserved balance-only account.
An alternative would be to preserve the whole account, including nonce, code, and storage. That would work as a complete SELFDESTRUCT disarming and would remove the burn as well, but it would be a larger semantic change than necessary. This SIP removes only the burn behavior.
Backwards Compatibility
This SIP requires a hard fork, since it modifies consensus rules.
Previously it was possible to burn SIL by executing SELFDESTRUCT in a contract created in the same transaction, either by targeting the executing contract as beneficiary or by sending SIL to the contract after SELFDESTRUCT and before transaction finalization. After this SIP, SIL will not be burned in either case.
Previously such contracts were always deleted at transaction finalization. After this SIP, a contract with zero final balance is still deleted, but a contract with nonzero final balance remains in the state as a balance-only account with empty code, empty storage, and nonce 0.
For the balance-only accounts created this way, CREATE2 still may recreate a contract at the same address in a follow-up transaction. Such a usage pattern remains operational.
For contracts not created in the same transaction in which SELFDESTRUCT is executed, the behavior is unchanged from SIP-6780.
Unlike SilaMainnet, some L2 chains use the burn feature of SELFDESTRUCT regularly and will require a separate migration plan.
In the OP Stack, SIL withdrawn to L1 accumulates in the L2ToL1MessagePasser predeploy at 0x4200000000000000000000000000000000000016. It provides a permissionless burn() function which destroys that balance by creating a contract whose constructor executes SELFDESTRUCT with itself as the beneficiary, so the L2 SIL supply does not inflate. Chains derived from that codebase inherit the dependency unless they modify the predeploy, including those not commonly identified as Optimism-based. Such contracts are deployed with CREATE, so the balance-only accounts they leave behind cannot be recreated by the CREATE2 pattern described above.
Test Cases
Unmodified behavior
General test coverage of the SELFDESTRUCT instruction is expected to be excellent already because this instruction has been modified multiple times in the past. Updating existing test cases to align with this SIP should give us good coverage of all unmodified features of SELFDESTRUCT.
Modified behavior
Each of the following test cases should be executed (where physically meaningful) across the combinations of these factors:
status: SELFDESTRUCT succeeds, SELFDESTRUCT fails due to OOG,
revert: effects of SELFDESTRUCT are committed to the post-state, effects of SELFDESTRUCT are reverted (only for wrapped internal calls),
balance: balance of the selfdestructing account at the SELFDESTRUCT instruction is zero / non-zero.
Instruction level
Same-transaction selfdestruct-to-self.
Same-transaction selfdestruct-to-self, followed by selfdestruct-to-self.
Same-transaction selfdestruct-to-self, followed by selfdestruct-to-other.
Same-transaction selfdestruct-to-other, followed by selfdestruct-to-self.
Transaction finalization
Same-transaction selfdestruct-to-other, followed by a CALL with value to the selfdestructed account.
Same-transaction selfdestruct-to-other, followed by multiple CALLs with value to the selfdestructed account.
Same-transaction selfdestruct-to-other, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-other.
Same-transaction selfdestruct-to-other, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-self.
Same-transaction selfdestruct-to-self, followed by a CALL with value to the selfdestructed account.
Same-transaction selfdestruct-to-self, followed by multiple CALLs with value to the selfdestructed account.
Same-transaction selfdestruct-to-self, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-other.
Same-transaction selfdestruct-to-self, followed by a CALL with value to the selfdestructed account, followed by selfdestruct-to-self.
Create new account, new account creates other accounts to bump its nonce, new account selfdestruct-to-self.
Create new account, new account creates other accounts to bump its nonce, new account selfdestruct-to-other.
Create new account, new account adds new storage, new account selfdestruct-to-self.
Create new account, new account adds new storage, new account selfdestruct-to-other.
Multi-transaction
Tx-1: CREATE2 new account with non-zero balance, new account selfdestruct-to-self. Tx-2: Repeats Tx-1.
Security Considerations
SELFDESTRUCT behavior modification has a combinatorial effect on a vast number of test scenarios involving multi-call/create contract interactions. This SIP requires significant testing effort. However, many existing test cases for SIP-6780 can be adapted to the new behavior.
When a use case relies on the SIL burn happening, the transaction will create dust-like accounts with potentially locked non-zero balance. However, the new account creation gas cost is paid by the transaction, so dust accounts are not a free DoS vector. Only 2 such events have been recorded on SilaMainnet (SilaCancun–25M) so far.
Preserving the balance leaves a funded account whose nonce, code and storage are cleared, which makes the address a valid CREATE2 target again (a non-zero balance alone never triggers a creation collision, per SIP-684). The (sender, salt, initcode) of a deployment is public data, so when the sender is a permissionless factory anyone can redeploy the account and potentially take the preserved balance.