如何校验外部地址向智能合约转账ETH的操作是否成功
核心逻辑解答
Solidity中被payable修饰的函数具备ETH接收能力,以太坊交易的原子性保证了:当函数进入执行逻辑时,调用方本次调用附带的ETH(即msg.value对应数额)已经自动从msg.sender账户扣除,转入合约地址,不存在「转账半途中进入函数执行」的情况,不需要额外做合约侧的入账校验。
如果你要求调用方必须转入指定数额的ETH,只需要加对应判断即可:
// 示例要求至少转入1wei ETH,可按需调整阈值 require(msg.value > 0, "Must send ETH to call this function");
完整实现参考
你需要先提前定义对应存储变量,实现存mapping再转作者的逻辑:
// 提前初始化:存储tokenId对应作者的地址,注意要定义为payable才能接收ETH mapping(uint => address payable) public tokenAuthor; // 按你的需求存入mapping:记录每个tokenId累计收到的ETH总额 mapping(uint => uint) public tokenTotalReceived; function sendToAuthor (uint tokenId) public payable{ // 校验1:本次调用确实转入了符合要求的ETH require(msg.value > 0, "No ETH sent in this call"); // 校验2:对应tokenId的作者地址有效 require(tokenAuthor[tokenId] != address(0), "Token does not exist"); // 先更新mapping存储记录 tokenTotalReceived[tokenId] += msg.value; // 给对应作者转账,推荐使用call方法兼容不同地址类型 (bool transferSuccess, ) = tokenAuthor[tokenId].call{value: msg.value}(""); // 校验给作者的转账结果,失败则整个交易回滚,ETH会退回给调用方 require(transferSuccess, "Failed to send ETH to author"); }
额外注意
- 上述写法遵循了Solidity官方推荐的Checks-Effects-Interactions模式:先做参数校验、再更新合约内部状态、最后做外部地址调用,天然可以规避大部分重入风险。
- 你不需要做任何额外逻辑校验
msg.sender给合约的转账是否成功:如果转账失败,整个交易会直接回滚,根本不会进入函数内部执行逻辑。
内容的提问来源于stack exchange,提问作者sun_dance
相关产品推荐
相关产品推荐

