---
title: Common Patterns
description: Copyable C SDK patterns for instruction validation, account
  mutation, CPI, logging, and derived addresses.
source_url:
  html: https://thru.org/docs/sdks/c-reference/common-patterns/
  md: https://thru.org/docs/sdks/c-reference/common-patterns.md
---

# Common Patterns

Use this page when you want a small, copyable pattern rather than a full API tour.

## Validate the instruction header first

```c
if( instr_sz < sizeof( my_instr_hdr_t ) ) tsdk_revert( 0x1000UL );
```

## Validate account indices before dereferencing

```c
if( !tsdk_is_account_idx_valid( account_idx ) ) {
  tsdk_revert( 0x1001UL );
}
```

## Read transaction instruction data once

```c
tsdk_txn_t const * txn = tsdk_get_txn( );
uchar const * instr = tsdk_txn_get_instr_data( txn );
ulong instr_sz = tsdk_txn_get_instr_data_sz( txn );
```

## Make account data writable before mutation

```c
if( tsys_set_account_data_writable( account_idx ) != TSDK_SUCCESS ) {
  tsdk_revert( 0x1002UL );
}
```

## Resize before writing a larger account payload

```c
if( tsys_account_resize( account_idx, sizeof( my_account_t ) ) != TSDK_SUCCESS ) {
  tsdk_revert( 0x1003UL );
}
```

## Read and write packed account data carefully

```c
my_account_t * account = (my_account_t *)tsdk_get_account_data_ptr( account_idx );
account->counter++;
```

If alignment is uncertain because you are reading from instruction bytes rather than account storage, prefer `TSDK_LOAD` and `TSDK_STORE`.

## Bubble up CPI failures explicitly

```c
ulong invoke_err = 0UL;
ulong invoke_result = tsys_invoke( payload, payload_sz, target_program_idx, NULL, &invoke_err );

if( invoke_result != TSDK_SUCCESS ) tsdk_revert( invoke_result );
if( invoke_err    != TSDK_SUCCESS ) tsdk_revert( invoke_err );
```

## Emit human-readable logs

```c
tsdk_printf( "counter=%lu", counter_value );
```

## Emit raw event payloads

```c
if( tsys_emit_event( event_bytes, event_sz ) != TSDK_SUCCESS ) {
  tsdk_revert( 0x1004UL );
}
```

## Derive a program-defined address

```c
tn_pubkey_t derived[1];
tsdk_create_program_defined_account_address( owner, 0U, seed, derived );
```

## Parse proof tails safely

```c
if( remaining_sz < sizeof( tsdk_state_proof_hdr_t ) ) tsdk_revert( 0x1005UL );

tsdk_state_proof_hdr_t const * hdr =
  (tsdk_state_proof_hdr_t const *)proof_ptr;

ulong proof_sz = tsdk_state_proof_footprint_from_header( hdr );
if( remaining_sz < proof_sz ) tsdk_revert( 0x1006UL );
```

## Notes

- The most reliable flow is: validate sizes, validate indices, validate ownership or auth, then mutate or invoke.
- If a page elsewhere shows a bigger end-to-end example, use this page as the short-form reference while implementing.
