---
title: Syscalls
description: Reference the Rust syscall wrappers in thru-core and the safe
  AccountManager methods that wrap them.
source_url:
  html: https://thru.org/docs/sdks/rust-program-sdk/syscalls/
  md: https://thru.org/docs/sdks/rust-program-sdk/syscalls.md
---

# Syscalls

Use this page when you need the low-level mutation and control operations the Thru VM exposes to Rust programs.

Every wrapper lives in `thru_core::syscall` and is compiled only for `riscv64` targets. All of them except `sys_exit` are `unsafe`, because they let the VM write to memory your program may still be holding references to. Prefer the `AccountManager` method in the last column: it checks borrows at runtime first.

## Return convention

Most wrappers return `SyscallCode`, an enum over the VM’s status values (`Success = 0`, `SuccessExit = 1`, errors negative). See [Error Handling and Return Codes](https://thru.org/docs/sdks/rust-program-sdk/error-handling-and-return-codes.md).

Two wrappers differ:

- `sys_invoke` returns `(SyscallCode, SyscallCode)`: the syscall-level result and the callee-level result.
- `sys_increment_anonymous_segment_sz` returns `(SyscallCode, *mut u8)`: the result and the new segment address.
- `sys_log` and `sys_emit_event` return the raw `u64` from the VM.
- `sys_exit` never returns.

## Account and balance syscalls

| Wrapper | Signature | Safe equivalent |
| - | - | - |
| `sys_set_account_data_writable` | `(account_idx: u64) -> SyscallCode` | `mgr.set_account_data_writable(idx)` |
| `sys_account_transfer` | `(from_idx: u64, to_idx: u64, amount: u64) -> SyscallCode` | `mgr.account_transfer(from, to, amount)` |
| `sys_account_create` | `(account_idx: u64, seed: &[u8; SEED_SIZE], proof: *const u8, proof_sz: u64) -> SyscallCode` | `mgr.account_create(idx, seed, proof)` |
| `sys_account_create_ephemeral` | `(account_idx: u64, seed: &[u8; SEED_SIZE]) -> SyscallCode` | `mgr.account_create_ephemeral(idx, seed)` |
| `sys_account_create_eoa` | `(account_idx: u64, signature: &Signature, proof: *const u8, proof_sz: u64) -> SyscallCode` | `mgr.account_create_eoa(idx, signature, proof)` |
| `sys_account_delete` | `(account_idx: u64, signature: Option<&Signature>) -> SyscallCode` | `mgr.account_delete(idx)` or `mgr.account_delete_signed(idx, signature)` |
| `sys_account_resize` | `(account_idx: u64, new_size: u64) -> SyscallCode` | `mgr.account_resize(idx, new_size)` |
| `sys_account_compress` | `(account_idx: u64, proof: *const u8, proof_sz: u64) -> SyscallCode` | `mgr.account_compress(idx, proof)` |
| `sys_account_decompress` | `(account_idx: u64, meta: *const u8, data: *const u8, proof: *const u8, proof_sz: u64) -> SyscallCode` | `mgr.account_decompress(idx, meta, data, proof)` |
| `sys_account_set_flags` | `(account_idx: u16, flags: u8) -> SyscallCode` | `mgr.account_set_flags(idx, flags)` |

The `AccountManager` variants take a `&StateProof` and pass its pointer and footprint for you, and they panic if the target account is currently borrowed. `mgr.create_and_init(idx, seed, proof, data_size)` combines create, make-writable, resize, and borrow into one call.

Account seeds are always `SEED_SIZE` (32) bytes.

## Control and diagnostics syscalls

| Wrapper | Signature | Notes |
| - | - | - |
| `sys_invoke` | `(instr_data: *const u8, instr_data_sz: u64, program_account_idx: u16, auth: *const u8) -> (SyscallCode, SyscallCode)` | Use `mgr.invoke(...)`; see [Cross-Program Invocation](https://thru.org/docs/sdks/rust-program-sdk/cross-program-invocation.md). |
| `sys_exit` | `(exit_code: u64, revert: u64) -> !` | Safe to call. Prefer `program_utils::succeed` / `program_utils::revert`. |
| `sys_log` | `(data: *const u8, data_sz: u64) -> u64` | Prefer `tvm_println!`. |
| `sys_emit_event` | `(data: *const u8, data_sz: u64) -> u64` | Emits an event payload for indexers and clients. |

## Memory syscalls

| Wrapper | Signature | Notes |
| - | - | - |
| `sys_set_anonymous_segment_sz` | `(addr: *mut u8) -> SyscallCode` | Sizes an anonymous segment; used by the generated boot shim for the stack. |
| `sys_increment_anonymous_segment_sz` | `(ptr: *mut (), delta: u64) -> (SyscallCode, *mut u8)` | Grows a segment. `program_utils::grow_stack(delta)` wraps this for the stack. |

## Syscall numbers

The syscall ids are public constants, useful when cross-referencing the [VM syscalls specification](https://thru.org/docs/spec/vm/syscalls/overview.md):

| Constant | Value |
| - | - |
| `SET_ANONYMOUS_SEGMENT_SZ` | `0x00` |
| `INCREMENT_ANONYMOUS_SEGMENT_SZ` | `0x01` |
| `SET_ACCOUNT_DATA_WRITABLE` | `0x02` |
| `ACCOUNT_TRANSFER` | `0x03` |
| `ACCOUNT_CREATE` | `0x04` |
| `ACCOUNT_CREATE_EPHEMERAL` | `0x05` |
| `ACCOUNT_DELETE` | `0x06` |
| `ACCOUNT_RESIZE` | `0x07` |
| `ACCOUNT_COMPRESS` | `0x08` |
| `ACCOUNT_DECOMPRESS` | `0x09` |
| `INVOKE` | `0x0A` |
| `EXIT` | `0x0B` |
| `LOG` | `0x0C` |
| `EMIT_EVENT` | `0x0D` |
| `ACCOUNT_SET_FLAGS` | `0x0E` |
| `ACCOUNT_CREATE_EOA` | `0x0F` |

## Segment addressing

VM addresses are `seg_type << 40 | seg_idx << 24 | offset`. `thru_core::mem` exposes the pieces:

```rust
use thru_core::mem::{compute_segment_addr, vm_ptr, SEG_TYPE_ACCOUNT_DATA};

let addr = compute_segment_addr(SEG_TYPE_ACCOUNT_DATA, account_idx as usize, 0);
let ptr: *const u8 = vm_ptr(SEG_TYPE_ACCOUNT_DATA, account_idx as usize, 0);
```

| Segment type | Value |
| - | - |
| `SEG_TYPE_READONLY_DATA` | `0x00` |
| `SEG_TYPE_ACCOUNT_METADATA` | `0x02` |
| `SEG_TYPE_ACCOUNT_DATA` | `0x03` |
| `SEG_TYPE_STACK` | `0x05` |
| `SEG_TYPE_HEAP` | `0x07` |

Read-only data segments are indexed by `SEG_IDX_TXN_DATA` (`0x0001`), `SEG_IDX_SHADOW_STACK` (`0x0002`), `SEG_IDX_PROGRAM` (`0x0003`), and `SEG_IDX_BLOCK_CTX` (`0x0004`).

For pointer work that must keep VM provenance, use `VmPtr<T>` / `VmPtrMut<T>` and the helpers `copy_nonoverlapping`, `copy_bytes_strict`, and `memset` from `thru_core::vmptr` instead of raw `core::ptr` calls.

## Related pages

- [Accounts and Transaction Context](https://thru.org/docs/sdks/rust-program-sdk/accounts-and-transaction-context.md)
- [VM syscalls overview](https://thru.org/docs/spec/vm/syscalls/overview.md)
- [C SDK syscalls](https://thru.org/docs/sdks/c-reference/syscalls.md)
