|Remove beneficiary from the self_destruct syscall
FIP-0073: Remove beneficiary from the self_destruct syscall
Currently, actors can delete themselves and send away their funds (to another actor) in a single operation. Unfortunately, this doesn’t behave exactly like a normal transfer of funds and introduces some complexity. We propose to simplify this “self destruct” mechanism by requiring users to send away any remaining funds first through a normal send, if desired.
self::self_destruct(beneficiary) syscall transfers funds to some designated beneficiary before deleting the actor. We propose to remove the beneficiary from this syscall. Instead, the user will be able to pass a boolean to specify if any remaining funds should be burnt, or if the self-destruct operation should fail if there are any remaining funds.
self_destruct transfers funds in a non-standard way. I.e., it doesn’t send a message, it just implicitly transfers the funds. This means:
- This transfer won’t show up in traces. This is fixable without a FIP, but adds some complexity to parsing traces.
- It won’t automatically create the beneficiary, unlike a normal
send(requires a FIP to fix). This is a foot-gun because it behaves differently from how
- If we ever decide to implement some mechanism whereby actors can execute code whenever they receive funds, this syscall, as currently implemented, could pose an issue. E.g., it might cause reentrency on self-destruct.
We could fix the first two issues instead of removing the beneficiary and there may be ways to work around the third issue. However, that would add unnecessary complexity. This complexity is unnecessary as there’s already a way to transfer funds (the
Instead, this FIP proposed to fix this issue by reducing complexity: the
self_destruct syscall will be responsible for deleting the actor and that’s it. Sending away funds will be the responsibility of the actor.
We replace the
self_destruct(beneficiary: Address) syscall with a
self_destruct(burn: bool) syscall. This syscall will:
- Check if the actor is executing in “read-only” mode. If so, the syscall will fail as it currently does.
- Check if there are remaining funds. If there are:
false, this syscall will fail with an
IllegalOperationerror number (0x2).
true, the funds will be transferred to the burnt funds account (charging no additional gas).
- Proceed to delete the actor.
No Charge Burn Funds
There’s no additional gas charge to burn funds as:
- We’ll already charge to update the actor being deleted.
- We don’t charge to update the burnt-funds actor per FIP-0057.
So any additional cost for burning funds is negligible.
Burning v. Erroring
We considered two potential implementations of
- The first we considered was to always return an error when
self_destructis called and there are remaining unspent funds in the actor.
- We also considered always burning funds.
We settled on a boolean flag because neither option is strictly superior. Passing a flag forces the user to make an explicit decision.
If we ever introduce account abstractions, accounts may want to “delete” themselves. It’s unclear whether or not we even want to allow this however, if we do, we’ll run into an issue: the account will be refunded for any unused gas after it has self-destructed. If a beneficiary is specified in
self_destruct, this is less of an issue as the unspent gas can simply be sent to said beneficiary.
However, I’m not particularly concerned about this for a few reasons:
- It’s unclear whether or not we’ll even allow this.
- This is already an issue even with the syscall as specified today as the beneficiary may self-destruct, leaving the FVM no place to send the refund from unused gas.
- Said refund will usually be negligible.
This FIP changes a syscall used by exactly one actor: the payment channel. Changing the payment channel actor to use the new syscall is trivial and already implemented in https://github.com/filecoin-project/builtin-actors/pull/1362.
The implementation includes unit tests.
This FIP has negligible risk from a security standpoint.
This FIP has no impact on network incentives.
This FIP removes a potential foot-gun (
self_destruct not behaving like
send) and simplifies the FVM a bit.
- FVM: https://github.com/filecoin-project/ref-fvm/pull/1838
- Builtin Actors: https://github.com/filecoin-project/builtin-actors/pull/1362
Copyright and related rights waived via CC0.
Please cite this document as:
Steven Allen, "FIP-0073: Remove beneficiary from the self_destruct syscall," Filecoin Improvement Proposals, no. 0073, August 2023. [Online serial]. Available: https://fips.filecoin.io/fips/fip-0073.