Skip to content

ABI 与调用数据 ​

合约调用是一笔发往 .app 地址的交易,其 data 字段携带调用内容。规范的载荷格式是 UTF-8 JSON:

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

在交易中,data 以字符串形式保存这段 JSON(也接受十六进制编码的载荷)。节点把这些字节交给合约的 call(input_ptr, input_len) 导出函数。

规则 ​

规则原因
方法名放在 function 中。旧合约也接受 method;新代码不应再使用。
身份来自宿主。 调用 get_caller();忽略 JSON 中的任何 caller 字段。任何人都可以往 JSON 里写任意 caller。宿主给出的值是经过验证的交易签名者(在跨合约调用中则是发起调用的合约)。
发送紧凑 JSON。 : 和 , 之后不留空格——即 JSON.stringify 的输出。小型 no_std 合约通过逐字节扫描 "key": 来读取参数;空白会使其失效。
金额用十进制字符串表示,单位为整枚代币:"amount":"250"。节点会进行换算(见下文);字符串可避免 JavaScript 中的精度损失。
args 中的参数名保持唯一。逐字节扫描的合约会在载荷中任意位置找到第一个 "key":,因此 args 也可以平铺在顶层传入。

金额由节点换算 ​

在调用到达合约之前,节点会替你改写一个参数:

  • 合约调用: 以十进制字符串或数字给出的 args.amount 被视为整枚代币金额,并按合约的 decimals 换算为代币的最小单位(6 位小数时 "250" → 250000000)。
  • 部署: init_args.total_supply 以同样方式按 init_args.decimals 换算,后者必须是 JSON 数字(字符串会被当作 0 位小数)。

其他所有参数都按原样到达合约。合约永远看不到人类可读的金额。

附带金额 ​

交易的 value(单位 uNRO)在调用成功之后记入合约自己的账户。如果调用 trap 或耗尽 fuel,金额留在发送方。目前没有宿主函数能告诉合约附带了多少金额;需要该信息的合约可以比较调用前后的 get_balance(),或把金额作为参数传入并加以校验。

返回数据与错误 ​

合约通过 set_return(ptr, len) 返回字节。按约定:

json
{"ok":"<value>"}            // 成功
{"error":"Unknown function"}  // 合约报告的失败

合约一旦 trap(unreachable、耗尽 fuel、越界访问内存),交易即失败:存储变更被回滚,金额不转移,手续费和 nonce 照常消耗。状态:failed。

无需交易即可读取返回值:

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}'

响应包含 success、return_data、gas_used 以及该调用将会发出的事件。当节点以 CHAIN_ENV=mainnet 运行时,通过此端点的写调用(dry_run: false)会被拒绝;请改为发送交易。

构造函数与 initialize ​

  • 如果存在 init 导出,它会在合约部署时运行一次。
  • 如果部署携带 init_args,随后会以 {"function":"initialize", …init_args} 调用合约——参数平铺在顶层。参见部署合约。

标准接口 ​

接口是有文档的方法集合,而不是额外的 WASM 导出:合约只要响应这些函数名,就实现了该接口。

NRC-20(同质化代币) ​

由 neurochain/contracts/nrc20 实现。在合约内部,所有金额都是以代币最小单位表示的整数;以整枚代币发送 amount,由节点换算(见上文)。

函数参数说明
initializename、symbol、decimals、total_supply仅一次;把全部供应量铸造给调用者,调用者成为 owner
name、symbol、decimals、total_supply—读取
balance_ofaddress读取
transferto、amount从调用者转出
approvespender、amount
allowanceowner、spender读取
transfer_fromfrom、to、amount消耗授予调用者的额度
mintto、amount仅限 owner
burnamount从调用者扣除
owner—读取

也接受 camelCase 别名(balanceOf、totalSupply、transferFrom)。转账会发出 Transfer 事件。

仓库中使用的其他接口:NRC-721 风格的证书(ncert)和 DAO 治理(dao、gov_dao);它们的 ABI 文件与源码放在一起(*.abi.json)。

跨合约调用 ​

合约可以通过宿主函数 call_contract 调用另一个合约,最多嵌套 8 层(MAX_CALL_DEPTH)。在被调用方内部,get_caller() 返回发起调用的合约地址。参见跨合约调用。