Skip to content

ABI & call data ​

A contract call is a transaction to a .app address whose data field carries the call. The canonical payload is UTF-8 JSON:

json
{"function":"transfer","args":{"to":"neuro:bob.human","amount":"250"}}

In a transaction, data holds this JSON as a string (a hex-encoded payload is also accepted). The node hands the bytes to the contract's call(input_ptr, input_len) export.

Rules ​

RuleWhy
Use function for the method name.Older contracts also accepted method; new code should not.
Identity comes from the host. Call get_caller(); ignore any caller field in the JSON.Anyone can write any caller into JSON. The host value is the verified signer of the transaction (or the calling contract, in a cross-contract call).
Send compact JSON. No spaces after : or , — JSON.stringify output.Small no_std contracts read arguments with a byte scan for "key":; whitespace breaks it.
Amounts as decimal strings in whole tokens: "amount":"250".The node converts them (see below); strings avoid precision loss in JavaScript.
Keep argument names unique across args.A byte-scanning contract finds the first "key": anywhere in the payload, so args may also be passed flattened at the top level.

Amounts are converted by the node ​

Before a call reaches the contract, the node rewrites one argument for you:

  • Contract calls: args.amount given as a decimal string or number is treated as a whole-token amount and converted to the token's smallest unit using the contract's decimals ("250" at 6 decimals → 250000000).
  • Deploys: init_args.total_supply is converted the same way using init_args.decimals, which must be a JSON number (a string is read as 0 decimals).

Every other argument reaches the contract exactly as sent. A contract never sees the human amount.

Attached value ​

The transaction's value (in uNRO) is credited to the contract's own account after the call succeeds. If the call traps or runs out of fuel, the value stays with the sender. There is currently no host function that tells the contract how much was attached; a contract that needs it can compare get_balance() before and after, or take the amount as an argument and verify it.

Return data and errors ​

A contract returns bytes with set_return(ptr, len). By convention:

json
{"ok":"<value>"}            // success
{"error":"Unknown function"}  // failure reported by the contract

A contract that traps (unreachable, out of fuel, out-of-bounds memory access) fails the transaction: storage changes are rolled back, the value is not moved, and the fee and nonce are consumed. Status: failed.

Read the return value without a transaction:

bash
curl -s -X POST "$GATEWAY/api/v1/contracts/neuro:<10 hex>.app/call" \
  -H 'Content-Type: application/json' \
  -d '{"function":"balance_of","args":{"address":"neuro:<15 hex>.human"},"dry_run":true}'

The response has success, return_data, gas_used and the events the call would emit. Write calls through this endpoint (dry_run: false) are refused when the node runs with CHAIN_ENV=mainnet; send a transaction instead.

Constructor and initialize ​

  • An init export, if present, runs once when the contract is deployed.
  • If the deploy carries init_args, the contract is then called with {"function":"initialize", …init_args} — arguments flattened into the top level. See Deploy contracts.

Standard interfaces ​

Interfaces are documented method sets, not extra WASM exports: a contract implements one by answering its function names.

NRC-20 (fungible token) ​

Implemented by neurochain/contracts/nrc20. Inside the contract every amount is an integer in the token's smallest unit; send amount in whole tokens and the node converts it (see above).

FunctionArgumentsNotes
initializename, symbol, decimals, total_supplyOnce; mints the supply to the caller, who becomes owner
name, symbol, decimals, total_supply—Read
balance_ofaddressRead
transferto, amountFrom the caller
approvespender, amount
allowanceowner, spenderRead
transfer_fromfrom, to, amountSpends an allowance granted to the caller
mintto, amountOwner only
burnamountFrom the caller
owner—Read

camelCase aliases (balanceOf, totalSupply, transferFrom) are accepted. Transfers emit a Transfer event.

Other interfaces used in the repository: NRC-721 style certificates (ncert) and DAO governance (dao, gov_dao); their ABI files sit next to the source (*.abi.json).

Cross-contract calls ​

A contract can call another with the host function call_contract, up to 8 levels deep (MAX_CALL_DEPTH). Inside the callee, get_caller() returns the calling contract's address. See Cross-contract.