FIP-0073 Source

TitleRemove beneficiary from the self_destruct syscall
AuthorSteven Allen
Discussions-Tohttps://github.com/filecoin-project/FIPs/discussions/524
StatusFinal
TypeTechnical Core
Created2023-08-29

Spec Sections

FIP-0073: Remove beneficiary from the self_destruct syscall

Simple Summary

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.

Abstract

Currently, the 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.

Change Motivation

Unfortunately, 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:

  1. This transfer won’t show up in traces. This is fixable without a FIP, but adds some complexity to parsing traces.
  2. 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 send currently behaves.
  3. 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 send syscall).

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.

Specification

We replace the self_destruct(beneficiary: Address) syscall with a self_destruct(burn: bool) syscall. This syscall will:

  1. Check if the actor is executing in “read-only” mode. If so, the syscall will fail as it currently does.
  2. Check if there are remaining funds. If there are:
    1. If burn is false, this syscall will fail with an IllegalOperation error number (0x2).
    2. If burn is true, the funds will be transferred to the burnt funds account (charging no additional gas).
  3. Proceed to delete the actor.

Design Rationale

No Charge Burn Funds

There’s no additional gas charge to burn funds as:

  1. We’ll already charge to update the actor being deleted.
  2. 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 self_destruct:

  1. The first we considered was to always return an error when self_destruct is called and there are remaining unspent funds in the actor.
  2. 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.

Account Abstraction

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:

  1. It’s unclear whether or not we’ll even allow this.
  2. 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.
  3. Said refund will usually be negligible.

Backwards Compatibility

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.

Test Cases

The implementation includes unit tests.

Security Considerations

This FIP has negligible risk from a security standpoint.

Incentive Considerations

This FIP has no impact on network incentives.

Product Considerations

This FIP removes a potential foot-gun (self_destruct not behaving like send) and simplifies the FVM a bit.

Implementation

  • 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.

Citation

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.