本文将介绍两种常见转账的实现方式,以及它们在 Yul 中的对应写法和 gas 费用的比较。
在 Solidity 中,实现合约向特定地址转账有多种方法。本文将介绍两种常见的实现方式,以及它们在 Yul 中的对应写法和 gas 费用的比较。
contract WithdrawV1 {
constructor() payable {}
address public constant owner = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
function withdraw() external {
(bool s,) = payable(owner).call{value: address(this).balance}("");
require(s);
}
}
contract WithdrawV2 {
constructor() payable {}
address public constant owner = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
function withdraw() external {
assembly {
let s := call(gas(), owner, selfbalance(), 0, 0, 0, 0)
if iszero(s) { revert (0, 0) }
}
}
}
在上面的代码中:
WithdrawV1
合约使用 Solidity
的 call
方法向 owner
地址发送交易,转账金额为合约中的全部余额,消息内容为空。WithdrawV2
合约中,用的是 call(gas(), owner, selfbalance(), 0, 0, 0, 0)
。因为不需要返回数据,所以 out
和 outsize
都设为 0。(bool s,) = payable(owner).call{value: address(this).balance}("");
语句的作用是向 owner
地址发送一笔金额为合约余额的交易,消息体为空。(bool s, bytes memory returnArr)
这种写法也可以用于获取返回值,但由于此处只是简单的转账给外部地址,返回值被忽略了。
在 Solidity 中,另一个常用的转账方法是 transfer
。例如,使用 payable(owner).transfer(address(this).balance);
也可以完成相同的功能。对应的 Yul 代码为:let s := call(2300, owner, selfbalance(), 0, 0, 0, 0)
,其中 2300 固定 gas 限制用于防止接收方执行更多复杂操作,只能发送事件或简单的状态更新。
尽管 WithdrawV1 和 WithdrawV2 两种合约功能相同,但在部署和每次调用时的 gas 费用存在差异。
WithdrawV1
, 并且部署的时候发送 1 个 ether, 总花费 156689
gas, 部署...如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!