Skip to content

Common Gotchas

View as Markdown

Use this page when you want the shortest list of things most likely to break an implementation.

1. Treat tsdk_return and tsdk_revert as terminal

Section titled “1. Treat tsdk_return and tsdk_revert as terminal”

They both end execution through tsys_exit. Any code after them is unreachable.

2. Do not trust account indices from instruction payloads

Section titled “2. Do not trust account indices from instruction payloads”

Always run tsdk_is_account_idx_valid(...) before reading metadata, data pointers, or issuing syscalls with an account index taken from instruction bytes.

3. A data pointer is not the same thing as writable permission

Section titled “3. A data pointer is not the same thing as writable permission”

tsdk_get_account_data_ptr(...) gives you an address, not permission. If you intend to mutate data, the account usually needs to be writable in context, and many flows should call tsys_set_account_data_writable(...) first.

Check both:

  • the syscall return value
  • the callee error in invoke_err_code

Ignoring one of them causes misleading CPI behavior.

5. Auth entries for CPI must be owned by the current program

Section titled “5. Auth entries for CPI must be owned by the current program”

The wrapper validates this before the syscall and can revert locally if you authorize an account your program does not own.

Do not use sizeof( tsdk_state_proof_t ) as the received proof length. Read the header and call tsdk_state_proof_footprint_from_header(...).

7. Transaction and proof structs are layout-sensitive

Section titled “7. Transaction and proof structs are layout-sensitive”

Several public structs are packed or represent wire-aligned layouts. Avoid casual casting from arbitrary byte buffers without checking size and alignment assumptions.

8. tsdk_printf is for debugging, not unlimited output

Section titled “8. tsdk_printf is for debugging, not unlimited output”

It formats into a fixed local buffer and ultimately logs through tsys_log.

9. Prefer helper accessors over manual VM address math

Section titled “9. Prefer helper accessors over manual VM address math”

The segment constants and TSDK_ADDR(...) are public, but most tasks are safer with helpers like tsdk_get_txn, tsdk_get_account_meta, and tsdk_get_current_block_ctx.

10. Start with tn_sdk.h unless the task is clearly lower level

Section titled “10. Start with tn_sdk.h unless the task is clearly lower level”

Agents can easily overcomplicate C SDK usage by pulling in too many low-level headers too early. The umbrella include is the right default.

11. Build against the installed SDK, not the repo-local SDK internals

Section titled “11. Build against the installed SDK, not the repo-local SDK internals”

For end-user workflows, prefer:

  • thru dev toolchain install
  • thru dev sdk install c
  • thru_c_program.mk

not direct reliance on repo-local setup scripts.

Large monolithic entrypoints make it harder for both humans and agents to reason about validation and mutation ordering. Validate early, dispatch quickly, and push real logic into helpers.