创建简单Escrow托管合约时currentState未更新且调用报错的问题求助
问题诱因
- 核心语法错误:两处状态赋值均误用相等比较运算符
==,该运算符仅返回布尔值,单独作为语句执行时无链上状态变更效果:confirmPayment函数中currentState == State.AWAITING_DELIVERY;仅做相等性判断,未执行赋值操作,函数调用后状态永远停留在初始值AWAITING_PAYMENT(枚举值0)confirmDelivery函数中currentState == State.COMPLETE;存在同类语法错误,即使前置状态更新成功,也不会将状态置为完成态
confirmDelivery调用直接回退的原因:因currentState始终为0,inState(State.AWAITING_DELIVERY)修饰符内的require判断失败,触发回退。IDE提示的“需要添加payable修饰符”为通用误导提示,该函数本身无需接收ETH,不存在payable相关问题。- 潜在逻辑缺陷:0.4.21版本中
address.send()为低级别调用,仅返回布尔值不触发异常,若转账失败不会自动回退交易,会出现资金未转出但状态已更新的资金安全问题。
修复方案
- 修正两处运算符错误:将
==替换为赋值运算符=,确保状态更新逻辑生效 - 补充
send返回值校验:转账失败时直接触发回退,避免资金损失 - 显式标记函数可见性、声明初始状态,提升代码可读性
修复后完整代码:
pragma solidity ^0.4.21; contract Escrow { enum State {AWAITING_PAYMENT, AWAITING_DELIVERY, COMPLETE} State public currentState; address public buyer; address public seller; modifier buyerOnly() { require(msg.sender == buyer); _; } modifier inState(State expectedState) { require(currentState == expectedState); _; } constructor(address _buyer, address _seller) public { buyer = _buyer; seller = _seller; currentState = State.AWAITING_PAYMENT; // 显式声明初始状态 } function confirmPayment() public buyerOnly inState(State.AWAITING_PAYMENT) payable { currentState = State.AWAITING_DELIVERY; // 修正运算符错误 } function confirmDelivery() public buyerOnly inState(State.AWAITING_DELIVERY) { // 校验转账结果,失败直接回退 require(seller.send(this.balance)); currentState = State.COMPLETE; // 修正运算符错误 } }
已部署旧合约的处理方式
如果已部署的旧合约中已经存入2ETH,无需重新部署,直接使用修复后的接口ABI调用confirmPayment方法(本次调用无需再转入ETH,资金已在合约内),状态即可更新为AWAITING_DELIVERY,后续即可正常调用confirmDelivery完成全流程。
内容的提问来源于stack exchange,提问作者Clifton Aurelius
相关产品推荐
相关产品推荐

