部署合约
部署是一笔发往 neuro:system.deploy 的普通签名交易。每个验证者都会在共识中用 VMGuardian 审计字节码;未通过审计的合约在任何地方都不会被创建。
1. 构建
合约是以 cdylib 形式编译到 wasm32-unknown-unknown 的 no_std Rust 代码,从 env 模块导入宿主函数——用 #[link(wasm_import_module = "env")] 声明它们,才能与当前版本的 Rust 正确链接。接口说明和完整示例见 NeuroWASM。
[lib]
crate-type = ["cdylib"]
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1cargo build --release --target wasm32-unknown-unknown
od -An -tx1 -v target/wasm32-unknown-unknown/release/my_contract.wasm | tr -d ' \n' > my_contract.hex十六进制必须以 0061736d(WASM 魔数)开头。字节码最大 512 KiB(MAX_BYTECODE_SIZE)。
仓库中可用的示例:neurochain/contracts/nrc20(同质化代币)、ncert(安全证书,NRC-721 风格)、dao 和 gov_dao。
2. 发送前检查 可选
| 端点 | 返回内容 |
|---|---|
POST /api/v1/contracts/analyze { "bytecode_hex": "…" } | risk_score、security_score、ml_score、model、violations——与关卡运行的分析相同 |
POST /api/v1/contracts/attest { "bytecode_hex": "…" } | 同样的结果,由节点用 ML-DSA-65 签名,可在浏览器中验证 |
Web 应用的部署页面会先在浏览器中运行分析,然后向节点请求签名的证明。
3. 发送部署
使用 SDK(推荐):
await nc.deployContract({
wallet,
bytecodeHex,
name: 'MyToken', // 唯一的合约名称,可选
description: '…',
template: 'nrc20', // 已注册模板的 id,可选
initArgs: { … }, // 传给 initialize,可选;decimals 用数字
gasPrice,
})手动发送——POST /api/v1/transactions,其中 to: "neuro:system.deploy"、value: 0,data 设为如下 JSON 字符串:
{ "bytecode_hex": "0061736d…", "name": "MyToken", "description": "", "template": "", "init_args": { } }签名方式与任何交易相同(nc-tx-v2|from|neuro:system.deploy|0|nonce)。
节点还提供 POST /api/v1/contracts/deploy(owner、bytecode_hex 或 base64_wasm,外加针对 neuro:system.deploy 的签名操作);它会替你构造同样的交易。
4. 每个验证者做什么
- 关卡。 解码字节码并查找其 SHA3-256 哈希:
- 在白名单中(如 NRC-20 等官方模板)→ 安全分数 100,不做分析;
- 关卡已被治理关闭(
deploy_security_enabled = 0)→ 中性分数 70; - 否则运行 VMGuardian
analyze_v2。如果risk_score ≥ deploy_risk_threshold(默认 0.80),交易失败且不收取手续费,拒绝记录连同违反的规则一起写入日志,并由nc_deploy_rejected_total指标计数。
- 扣费 10 000 gas 单位 ×
gas_price。 - 创建合约,地址为
neuro:<10 hex>.app——即SHA3-256(owner ‖ nonce)的前 5 个字节。如果合约名称已被其他合约占用,部署失败。 - 构造函数。 如果模块导出
init,它会在部署的存储上运行一次。 - 初始化。 如果存在
init_args,会以{"function": "initialize", …init_args}调用合约——参数平铺在 JSON 顶层——调用者是你。 - 模板费用。 如果
template指向一个带费用的已注册模板,该费用从你转给模板作者。
最终的安全分数为 100 − risk_score × 100,与合约一起存储。
费用
| 项目 | 费用 |
|---|---|
| 部署 | 10 000 gas 单位 × gas_price(按 1 uNRO 计:0.01 NRO) |
| 被关卡拒绝 | 不收费 |
| 模板 | 模板自身的费用(如有) |
部署后:持续监控
每个节点每 20 秒(MONITOR_INTERVAL_SECS)重新审计已部署的合约。当合约分数变化达到 10 分或以上(MONITOR_SCORE_THRESHOLD)——例如模型更新之后——会通过共识发出一笔证书更新交易。证书可通过 GET /api/v1/certificates/contract/:address 读取。参见 VMGuardian。
故障排查
| 错误 | 原因 |
|---|---|
Deploy rejected by VMGuardian: risk_score … >= threshold … | 审计发现了有风险的模式;analyze 会列出它们。 |
gas_price … below block base_fee … | 把 gasPrice 提高到当前基础费用之上。 |
Contract name '…' is already taken | 换一个 name,或留空。 |
| 大小错误 | 字节码超过 512 KiB——用 opt-level = "z" 和 LTO 构建。 |