Solidity跨合约发送ETH触发交易回退报错问题咨询
报错根因
交易回滚的核心原因有两个,刚好对应报错提示的两种触发场景:
- 接收方合约
receiveEther没有定义可接收原生以太币的入口。Solidity 0.8版本强制要求:如果合约要接收不指定调用函数的直接ETH转账(即通过transfer()/send()发起的转账),必须显式声明receive() external payable函数;如果转账时匹配不到对应函数,还需要带payable修饰的fallback()兜底,否则EVM会直接终止交易,抛出“被调用函数需标记为payable”的错误。 - 发送方合约
sendEther的send()函数逻辑错误。当前代码固定向目标地址转1wei,既没有使用调用该函数时传入的msg.value作为转账金额,也没有提前校验合约自身余额是否足够支付转账,一旦余额不足就会触发回滚。另外0.8版本后transfer()方法硬编码的2300gas限制在很多场景下会导致转账意外失败,已经不推荐使用。
修复后代码
pragma solidity ^0.8.15; contract sendEther { function deposit() external payable {} function send(address payable _to) external payable { require(msg.value > 0, "transfer amount must be greater than 0"); // 用call方法替代transfer,避免gas限制问题,转账金额取调用时传入的msg.value (bool success, ) = _to.call{value: msg.value}(""); require(success, "ETH transfer failed"); } function getBalance() public view returns(uint){ return address(this).balance; } } contract receiveEther { // 新增receive函数,允许合约接收直接转入的ETH receive() external payable {} function getBalance() external view returns(uint){ return address(this).balance; } }
验证流程
修复后按以下步骤操作即可正常完成转账:
- 部署两个合约后,调用
sendEther.deposit()存入任意金额ETH,可通过sendEther.getBalance()确认余额到账。 - 调用
sendEther.send(),参数填入receiveEther的合约地址,同时在交易的Value字段填入你要转账的金额,发起交易。 - 调用
receiveEther.getBalance()即可查询到对应到账金额。
内容的提问来源于stack exchange,提问作者Thermal Ice
相关产品推荐
相关产品推荐

