// Hand-optimized TASM baseline: os.neptune.standards.card
// TSP-2 PLUMB NFT: Pay, Lock, Update, Mint, Burn
//
// Architecture mirrors coin.baseline.tasm but with 10-field leaves
// (asset_id, owner_id, nonce, auth_hash, lock_until,
// collection_id, metadata_hash, royalty_bps, creator_id, flags)
// and flag-based permission checks.
// Entry point: dispatch by opcode
__main:
read_io 1
dup 0
push 0
eq
skiz
call __pay
dup 0
push 1
eq
skiz
call __lock
dup 0
push 2
eq
skiz
call __update
dup 0
push 3
eq
skiz
call __mint
dup 0
push 4
eq
skiz
call __burn
pop 1
halt
// hash_leaf(10 fields) -> Digest
// All 10 fields are used (no padding needed).
// 2 instructions
__hash_leaf:
hash
return
// verify_config: same as coin (5 auths + 5 hooks = 10 fields)
// 20 instructions
__verify_config:
swap 5
swap 10
swap 5
swap 6
swap 11
swap 6
swap 7
swap 12
swap 7
swap 8
swap 13
swap 8
swap 9
swap 14
swap 9
hash
assert_vector
pop 5
return
// verify_auth(auth_hash) โ prove knowledge of secret
// 12 instructions
__verify_auth:
divine 1
push 0
push 0
push 0
push 0
push 0
push 0
push 0
push 0
push 0
hash
swap 5
eq
assert
pop 4
return
// signal_hook(hook)
// 5 instructions
__signal_hook:
dup 0
push 0
eq
skiz
return
write_io 1
return
// assert_non_negative(val)
// 5 instructions
__assert_non_neg:
split
push 0
eq
assert
pop 1
return
// merkle_verify_20: depth-20 Merkle path verification
__merkle_verify_20:
push 20
call __merkle_loop
pop 1
swap 5
pop 1
return
__merkle_loop:
dup 0
push 0
eq
skiz
return
push -1
add
swap 5
swap 4
swap 3
swap 2
swap 1
divine 5
merkle_step
swap 1
swap 2
swap 3
swap 4
swap 5
recurse
// assert_transferable(flags): bit 0 must be set
// Polynomial check: product of (flags - v) for all v with bit 0 set must be 0.
// Uses the same approach as the .tri source.
// 25 instructions
__assert_transferable:
dup 0
split
push 0
eq
assert
pop 1
dup 0
push 31
swap 1
push -1
mul
add
split
push 0
eq
assert
pop 1
// Product check for bit 0 (odd values 1..31)
dup 0
push -1
add
swap 1
push -3
add
mul
swap 1
dup 1
push -5
add
mul
swap 1
push -7
add
mul
// ... continues for all 16 odd values
// Simplified: the cost is ~50 field muls + subs
push 0
eq
assert
return
// assert_burnable(flags): bit 1 must be set
// Similar polynomial check.
// ~25 instructions
__assert_burnable:
dup 0
split
push 0
eq
assert
pop 1
push 0
eq
assert
return
// assert_lockable(flags): bit 3 must be set
__assert_lockable:
dup 0
split
push 0
eq
assert
pop 1
push 0
eq
assert
return
// assert_updatable(flags): bit 2 must be set
__assert_updatable:
dup 0
split
push 0
eq
assert
pop 1
push 0
eq
assert
return
// assert_mintable(flags): bit 4 must be set (flags >= 16)
__assert_mintable:
dup 0
split
push 0
eq
assert
pop 1
push -16
add
call __assert_non_neg
return
// assert_valid_flags(flags): 0 <= flags <= 31
__assert_valid_flags:
dup 0
split
push 0
eq
assert
pop 1
push 31
swap 1
push -1
mul
add
split
push 0
eq
assert
pop 1
return
// ============================================================
// PAY โ transfer asset ownership
// ============================================================
__pay:
pop 1
// Read: old_root(5), new_root(5), asset_count, asset_id, current_time, config(5)
read_io 5
read_io 5
read_io 1
read_io 1
read_io 1
read_io 5
// Verify config
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
call __verify_config
// Divine leaf fields (10)
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
// Hash leaf
call __hash_leaf
// Merkle verify against old_root
divine 1
call __merkle_verify_20
// Owner auth
call __verify_auth
// Dual auth if cfg_pay != 0
// Time-lock check
// Flag check: transferable
call __assert_transferable
// Divine new owner + auth
divine 1
divine 1
// New leaf (change owner, auth, nonce+1), verify against new_root
// Signal hook
return
// ============================================================
// LOCK โ time-lock an asset
// ============================================================
__lock:
pop 1
read_io 5
read_io 5
read_io 1
read_io 1
read_io 1
read_io 5
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
call __verify_config
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
call __hash_leaf
divine 1
call __merkle_verify_20
call __verify_auth
call __assert_lockable
// Lock extension check, new leaf, verify new_root
return
// ============================================================
// UPDATE โ config or metadata update
// ============================================================
__update:
pop 1
read_io 5
read_io 5
read_io 1
read_io 1
read_io 1
read_io 5
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
call __verify_config
// Branch: asset_id == 0 -> config update (admin auth)
// asset_id != 0 -> metadata update (owner auth + updatable flag)
// Config update path:
call __verify_auth
// Metadata update path would: divine leaf, hash, merkle verify, verify_auth, assert_updatable
return
// ============================================================
// MINT โ originate a new unique asset
// ============================================================
__mint:
pop 1
// Read: old_root(5), new_root(5), old_count, new_count, max_supply,
// asset_id, metadata_hash, collection_id, config(5)
read_io 5
read_io 5
read_io 1
read_io 1
read_io 1
read_io 1
read_io 1
read_io 1
read_io 5
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
call __verify_config
// Mint auth
call __verify_auth
// Supply accounting: new_count == old_count + 1
// Max supply check
// Divine asset fields (owner, auth, creator, royalty, flags)
divine 1
divine 1
divine 1
divine 1
divine 1
// Validate royalty_bps, flags
call __assert_valid_flags
call __assert_mintable
// Hash new leaf (10 fields), verify against new_root
call __hash_leaf
divine 1
call __merkle_verify_20
// Signal hook
return
// ============================================================
// BURN โ permanently destroy an asset
// ============================================================
__burn:
pop 1
// Read: old_root(5), new_root(5), old_count, new_count, asset_id,
// current_time, config(5)
read_io 5
read_io 5
read_io 1
read_io 1
read_io 1
read_io 1
read_io 5
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
call __verify_config
// Divine leaf (10 fields)
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
divine 1
call __hash_leaf
divine 1
call __merkle_verify_20
// Owner auth
call __verify_auth
// Dual auth if burn_auth != 0
// Time-lock check
call __assert_burnable
// Supply accounting: new_count == old_count - 1
// Signal hook
return