---
title: account_create
description: Creates a new permanent account with state proof verification
source_url:
  html: https://thru.org/docs/spec/vm/syscalls/account_create/
  md: https://thru.org/docs/spec/vm/syscalls/account_create.md
---

# account_create

## Overview

The `account_create` syscall creates a new permanent account using a program-defined address derived from a seed. The account creation requires a state proof to verify the address doesn’t already exist in the global state.

## Syscall Code

**Code:** `0x04` (`TN_SYSCALL_CODE_ACCOUNT_CREATE`)

## C SDK Function

```c
ulong tsys_account_create( ulong account_idx, uchar const seed[TN_SEED_SIZE],
                           void const * proof, ulong proof_sz );
```

## Arguments

**`account_idx` · *ulong* · **required****

Index of the account slot to create. Must be writable in the transaction and currently non-existent.

**`seed` · *uchar const\[TN\_SEED\_SIZE]* · **required****

Fixed 32-byte seed used for address derivation.

**`proof` · *void const** · **required***\*

Pointer to the state proof data.

**`proof_sz` · *ulong* · **required****

Size of the state proof data in bytes.

## Return Value

Returns a syscall result code:

**`Success` · *ulong***

- `TN_VM_SYSCALL_SUCCESS` (0) - Account created successfully

**`Error Codes` · *ulong***

- `TN_VM_ERR_SYSCALL_INVALID_ACCOUNT_INDEX` (-8) - Account index out of bounds
- `TN_VM_ERR_SYSCALL_ACCOUNT_NOT_WRITABLE` (-10) - Account not writable in transaction
- `TN_VM_ERR_SYSCALL_ACCOUNT_ALREADY_EXISTS` (-15) - Account already exists
- `TN_VM_ERR_SYSCALL_INVALID_ADDRESS` (-22) - Invalid virtual address for seed or proof
- `TN_VM_ERR_SYSCALL_BAD_ACCOUNT_ADDRESS` (-16) - Computed address doesn’t match expected
- `TN_VM_ERR_SYSCALL_INVALID_PROOF_LEN` (-32) - Proof size mismatch
- `TN_VM_ERR_SYSCALL_INVALID_PROOF_SLOT` (-33) - Proof references invalid block slot
- `TN_VM_ERR_SYSCALL_INVALID_STATE_PROOF` (-23) - State proof verification failed
- `TN_VM_ERR_SYSCALL_EPHEMERAL_ACCOUNT_CANNOT_CREATE_PERSISTENT` (-42) - Ephemeral account cannot create persistent account
- `TN_VM_ERR_SYSCALL_STATE_BYTES_ADDED_OVERFLOW` (-47) - State bytes counter overflow during activation

## Resource Consumption

### Compute Units

- **Base cost**: `TN_VM_SYSCALL_BASE_COST` (512 units)
- **Seed cost**: Additional units equal to `TN_SEED_SIZE` bytes
- **Proof cost**: Additional units equal to proof size in bytes
- **Metadata cost**: Additional units equal to `sizeof(tsdk_account_meta_t)`
- **Total formula**: `base_cost + TN_SEED_SIZE + proof_sz + sizeof(tsdk_account_meta_t)`

### Memory Pages

- **Page usage**: No direct page allocation (account data starts at size 0)
- **Metadata pages**: Allocates pages for account metadata structure
- **State proof validation**: Temporary memory usage for proof verification

### State Counter Impact

- **GASC (Global Activated State Counter)**: Incremented by `TSDK_ACCOUNT_META_FOOTPRINT` bytes
- **Purpose**: Tracks activated state for the account creation in the global state counter
- **Overflow protection**: Returns `TN_VM_ERR_SYSCALL_STATE_BYTES_ADDED_OVERFLOW` if counter would overflow

## Side Effects

- **Account creation**: Creates a new account with NEW flag set
- **Ownership**: Sets the current program as the account owner
- **Account metadata**: Initializes writable metadata structure

## Address Derivation

The account address is computed as:

```plaintext
SHA256(current_program_pubkey || is_ephemeral(0) || seed)
```

## State Proof Requirements

- **New accounts**: Requires a creation-type state proof showing the address doesn’t exist
- **Deleted accounts**: Can recreate without proof (removes DELETED flag)
- **Proof verification**: Must reference a valid block slot and verify against state root

## Usage Notes

- The computed account address must match the transaction’s expected address
- Seed must be exactly `TN_SEED_SIZE` (32 bytes)
- State proof ensures global uniqueness of the address
- Created accounts are owned by the calling program
- Account is implicitly marked as writable by the creating program

## Example

```c
#include <thru-sdk/c/tn_sdk_syscall.h>
#include <string.h>

// Create account with seed "my_account"
ulong account_idx = 5;
uchar seed[TN_SEED_SIZE] = { 0 };
memcpy( seed, "my_account", 10 );

// Prepare state proof data
uchar proof_data[1024];
ulong proof_size = prepare_creation_proof(proof_data);

ulong result = tsys_account_create( account_idx, seed, proof_data, proof_size );

if (result == TN_VM_SYSCALL_SUCCESS) {
    // Account created successfully
    // Account is owned by current program
    // Account has NEW flag set
}
```
