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

Solidity石头剪刀布(RPS)合约未出招校验逻辑疑问

结论:这段合约代码确实存在你所说的逻辑冲突,属于明显的设计漏洞

  • 首先明确Solidity的基础规则:mapping(address => uint8) public choices 这类映射类型,未手动赋值的键对应的默认值就是对应类型的零值,uint8的零值就是0。合约开发者原本的设计意图是用0代表「玩家未提交出招」的状态,但同时又将代表石头的常量ROCK赋值为0,二者确实会发生冲突。
  • 冲突会引发的具体问题:
    1. 玩家首次提交ROCK(值为0)出招后,choices[msg.sender]会被赋值为0,后续玩家仍然可以重复调用play函数修改出招——因为require(choices[msg.sender] == 0)的校验会一直通过,完全起不到「防止重复出招」的作用。
    2. 胜负判定逻辑会混乱:如果一个玩家未出招、另一个玩家出了ROCK,evaluate函数读取二者的choices值都是0,会错误判定为平局。
  • 常见的修复方案:
    方案一:调整出招常量的取值,避开零值。比如将ROCK赋值为1、PAPER为2、SCISSORS为3,零值0专门用来标识未出招的状态。
    方案二:新增独立的状态标记校验是否已出招,比如添加mapping(address => bool) public hasPlayed,play函数里改为校验require(hasPlayed[msg.sender] == false),出招成功后将hasPlayed[msg.sender]设为true即可,无需和出招值的取值范围耦合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 06:57:03