为什么我部署在Ropsten的Solidity智能合约无法转出1以太币?
问题原因及修复方案
- 合约无足够余额完成转账
你调用payRequest方法时发起的交易value为0,既没有在调用时向合约转入对应金额的ETH,也没有提前给合约充值ETH,合约账户本身没有可用于转出的余额,因此call操作返回的success字段为false,转账实际失败。 payRequest方法缺少payable修饰符
如果你希望调用payRequest的同时由调用方直接支付转账金额,必须给payRequest方法添加payable修饰符,否则该方法无法接收用户调用时附带的ETH。- 转账逻辑缺少校验规则
当前代码中即使call转账失败也不会回滚交易,还会正常触发RequestPaid事件,会造成转账成功的假象。你需要在收到success为false的返回后主动回滚交易,或者做对应的错误处理。
修复后参考代码
// SPDX-License-Identifier: MIT pragma solidity 0.7.4; pragma experimental ABIEncoderV2; contract Leger { struct TransferRequest { string title; uint256 amount; string bsb; string accountName; string accountNumber; } event PaymentReceive(address from, uint256 amount); event TransactionBytes(bytes transactionBytes); event RequestPaid(address receiver, uint256 amount); // 添加payable修饰符,允许调用时转入ETH function payRequest(address payable _recipient, uint256 _amount) public payable { // 校验调用方转入的ETH金额与约定转账金额一致 require(msg.value == _amount, "Transfer amount mismatch"); (bool success, bytes memory transactionBytes) = _recipient.call{value:_amount}(''); // 转账失败直接回滚交易 require(success, "Transfer to recipient failed"); emit TransactionBytes(transactionBytes); emit RequestPaid(_recipient, _amount); } receive() external payable { emit PaymentReceive(msg.sender, msg.value); } }
使用说明
- 采用上述修改方案后,调用
payRequest方法时,需要将交易的value设置为你要转账的1ETH,同时_amount参数也传入1ETH对应的wei数值(1ETH = 10^18 wei) - 如果你希望用合约预先存储的余额转账,不需要调用方每次转账,那么不需要给
payRequest加payable修饰符,但需要提前向合约地址转入足够的ETH,确保合约余额大于等于你要转出的_amount数值
内容的提问来源于stack exchange,提问作者Joey Yi Zhao
相关产品推荐
相关产品推荐

