You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clarity智能合约调用两次count-even后even-values为何仅为u1?

问题分析与解决

首先看你的Clarity合约代码:

(define-data-var even-values uint u0)
(define-public (count-even (number uint))
(begin
;; increment the "event-values" variable by one.
(var-set even-values (+ (var-get even-values) u1))
            ;; check if the input number is even (number mod 2 equals 0).
            (if (is-eq (mod number u2) u0)
                    (ok "the number is even")
                    (err "the number is uneven")
            )
    )
)
;; Call count-even two times.
(print (count-even u4))
(print (count-even u7))
;; Will this return u1 or u2?
(print (var-get even-values))

核心原因

你遇到的问题是调用count-even的方式为查询调用,而非会持久化状态的交易调用,或者你的执行环境在每次调用后自动回滚了状态。

Clarity对函数调用有严格区分:

  • 交易调用:用于修改合约状态,执行后变更会被永久保存,需要通过交易发起(比如钱包交易、Clarinet的call命令)。
  • 查询调用:仅用于模拟执行或读取数据,不会实际修改合约状态,所有临时状态变更在调用结束后都会被回滚。

你用(print (count-even u4))这种方式调用public函数,在绝大多数Clarity执行环境(如Clarinet Console、在线编辑器)中会被判定为查询调用,所以每次var-set的递增只是临时模拟,不会被保存到合约的持久化状态中。你看到返回u1,大概率是因为最后一次查询调用临时把状态改成了u1,但这不是真正的合约状态——如果单独查询var-get even-values,原本应该返回初始值u0,只是你在同一个查询脚本中连续执行调用,临时状态被保留到了脚本结束而已。

另外需要明确:Clarity中即使函数返回err,已经执行的var-set操作仍然会被持久化(只要是交易调用),所以两次交易调用后,even-values一定会变成u2。

解决方法

要让状态变更永久保存,你需要用交易调用执行count-even函数:

  • 在Clarinet Console中,使用call命令发起交易:
    call .count-even u4
    call .count-even u7
    
    之后再查询状态:
    print (var-get even-values)
    
    此时会返回u2。
  • 在Clarinet测试脚本中,用(contract-call? ...)发起交易调用:
    (contract-call? .count-even u4)
    (contract-call? .count-even u7)
    (asserts! (is-eq (var-get even-values) u2) "even-values should be u2")
    
  • 在区块链上部署合约后,通过钱包发起两次交易调用count-even,之后查询状态即可得到u2。

代码逻辑验证

你的合约逻辑本身是正确的:每次调用count-even,无论输入是奇数还是偶数,都会先执行var-set递增even-values,再返回对应结果。只要用交易调用触发,两次调用后even-values必然是u2。

内容的提问来源于stack exchange,提问作者Brian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:12:48