Skip to content

account_delete

View as Markdown

The account_delete syscall truncates account data to zero. For a permanent account with neither NEW nor EPHEMERAL set, it leaves DELETED clear and the account remains live and active. For a NEW or EPHEMERAL account, it also sets DELETED, leaving an inactive corpse that can be revived within the block or removed at block seal.

Creation sets NEW, and block finalization does not clear it. A created account stays in the NEW/corpse class until it has been compressed and decompressed, even if it is deleted much later. Decompression clears NEW, including the runtime’s fee-payer decompression path. Non-NEW accounts include decompressed accounts and genesis accounts provisioned without NEW.

The account must exist, have zero balance and nonce, be writable in the transaction, and be owned by the current program. If it has data, that data must also be writable by the current program.

Code: 0x06 (TN_SYSCALL_CODE_ACCOUNT_DELETE)

ulong tsys_account_delete( ulong account_idx, tn_signature_t const * signature );

account_idx · ulong · required

Index of the account to delete. Must satisfy the existence, ownership, write-access, zero-balance, and zero-nonce requirements above.

signature · tn_signature_t const * · optional

Pointer to an Ed25519 signature over the canonical delete message, verified against the account’s public key. Pass 0 or NULL for an ordinary program-owned account when no signature is required. The EOA program requires the account keyholder’s signature before deleting an EOA and passes it to this syscall. Supplying a signature does not bypass ownership or write-access checks.

The signed message concatenates the 16-byte ASCII domain tag tn_eoa_delete_v1 (without a terminating NUL), the two-byte little-endian chain ID, the 32-byte fee-payer public key, and the 32-byte account public key.

Returns a syscall result code:

Success · ulong

  • TN_VM_SYSCALL_SUCCESS (0) - Account data truncated; DELETED set only for NEW or EPHEMERAL accounts

Error Codes · ulong

  • TN_VM_ERR_SYSCALL_INVALID_ACCOUNT_INDEX (-8) - Account index out of bounds
  • TN_VM_ERR_SYSCALL_ACCOUNT_DOES_NOT_EXIST (-9) - Account does not exist
  • TN_VM_ERR_SYSCALL_ACCOUNT_NOT_WRITABLE (-10) - Account not writable by current program
  • TN_VM_ERR_SYSCALL_INVALID_ACCOUNT (-27) - Account has non-zero balance or non-zero nonce
  • TN_VM_ERR_SYSCALL_INVALID_SIGNATURE (-44) - Supplied Ed25519 signature fails verification against the account’s public key
  • Base cost: TN_VM_SYSCALL_BASE_COST (512 units)
  • Additional cost: 146 units when a signature is supplied (64 signature bytes + 82 canonical-message bytes)
  • Total cost: 512 units without a signature; 658 units with a signature
  • Page usage: Frees currently allocated account data pages and sets data_sz to zero
  • Metadata impact: Makes account metadata writable if needed
  • Record cleanup: Retains non-NEW, non-EPHEMERAL records; retains deleted-class corpse metadata until revival or block seal

State units are metered from committed account endpoints after execution, not by unconditionally adding metadata and data bytes during this syscall. A truncated permanent account remains active and contributes one state unit. A NEW or EPHEMERAL deleted corpse is inactive and contributes no active state units.

  • Non-NEW, non-EPHEMERAL accounts: Preserve flags and remain live with empty data
  • NEW or EPHEMERAL accounts: Set DELETED and become inactive, non-existing corpses
  • Data: Truncate immediately; old data is not available after deletion
  • Metadata: Retain the record for non-NEW, non-EPHEMERAL accounts and for corpses awaiting revival or block seal
  • Account balance and nonce must both be zero
  • Only the account owner program can call this syscall successfully, with the required transaction and data write access
  • A truncated permanent account still exists; creation and decompression at that address return TN_VM_ERR_SYSCALL_ACCOUNT_ALREADY_EXISTS, subject to their other preconditions
  • Deletion does not restore an old compressed preimage or make an old proof usable again
  • The matching creation syscall can revive a deleted-class corpse at the same address within the block under its normal checks, preserving sequence continuity: account_create or account_create_eoa for a non-ephemeral NEW|DELETED corpse, and account_create_ephemeral for an EPHEMERAL|DELETED corpse. Ephemeral addresses use a different derivation; decompression cannot revive a corpse
  • Corpses that remain deleted are removed at block seal, not after each transaction
  • Legacy plain-DELETED tombstones remain persisted and active for state accounting but do not exist for most account operations; the matching account_create or account_create_eoa call revives one in place without a creation proof, subject to its other checks, and decompression rejects it with TN_VM_ERR_SYSCALL_ACCOUNT_ALREADY_EXISTS. Current permanent deletion does not produce these tombstones
OperationPurposeRequirementsEffect
Delete non-NEW, non-EPHEMERAL accountClear account dataZero balance and nonce, ownership, write accessTruncates data; account remains live and active
Delete NEW or EPHEMERAL account (includes created accounts until compressed and decompressed, regardless of age)Deactivate accountZero balance and nonce, ownership, write accessSets DELETED and truncates data; retains corpse until revival or block seal
Compress account (normal compression path)Move account out of active stateState proof and compression eligibility checksSets COMPRESSED; removes live record at save time

Compression of an EPHEMERAL account, or a NEW account with zero balance, nonce, and data size, instead follows the deleted-corpse path. See tsys_account_compress() and the account lifecycle.

#include <thru-sdk/c/tn_sdk_syscall.h>
/* Delete or truncate an ordinary program-owned account with zero balance
and nonce. The caller must have ownership and write access.
Return the syscall result so the caller can handle failure. */
ulong
tn_example_delete_account( ulong account_idx ) {
/* No signature required for an ordinary program-owned account. */
return tsys_account_delete( account_idx, NULL );
}