Solidity继承和抽象,转账函数
继承
抽象合约
abstract contract Parent { uint256 public value; // 不可被继承 uint256 private notInheritValue; function addOne() public { value++; } // 强制子合约实现此函数 function addTwo() public virtual; // 不强制子合约实现此函数,提供了默认实现 function addThree() public virtual { value += 3; } } contract Child is Parent{ // 实现virtual function,显示声明override function addTwo() public override { value+=2; } // 重写父合约的默认实现 function addThree() public override { value += 3; } }
Transfer
Solidity中有3种转账函数:
Transfer
transfer
函数是address
类型的成员函数,以wei
为单位进行转账;
- 转账失败自动回滚交易,仅损失gas,不会损失转账的金额;
contract MyContract { // 收款人地址 address payable public recipient; constructor(address payable _recipient) { recipient = _recipient; } // 执行转账 function sendEther() public payable { // 检查发送的以太币数量是否大于0 require(msg.value > 0, "You need to send some Ether"); // 将合约收到的所有以太币转账给recipient recipient.transfer(msg.value); } }
Send
send
函数是address
类型的成员函数,以wei
为单位进行转账;
- 转账失败不会自动回滚交易,函数返回false;
- 需要手动revert来回滚交易;
contract MyContract { // 收款人地址 address payable public recipient; constructor(address payable _recipient) { recipient = _recipient; } // 执行转账 function sendEther() public payable { // 检查发送的以太币数量是否大于0 require(msg.value > 0, "You need to send some Ether"); // 将合约收到的所有以太币转账给recipient bool result = recipient.send(msg.value); if (!result) { revert("Transfer Failed") } } }
Call
transfer
、send
都仅可执行Eth的转账操作;
call
函数不仅可转账,还可以调用其他合约的函数,更灵活,更强大;
- 可以携带更多的参数,转账时则是指定转账金额的参数;
- 转账失败有几种情况:
- gas不足:call函数可以设置gas limit,如果gas不足则会失败;
- 接收方合约异常:对方的fallback、receive函数执行失败;
contract MyContract { // 收款人地址 address payable public recipient; constructor(address payable _recipient) { recipient = _recipient; } // 执行转账 function sendEther() public payable { // 检查发送的以太币数量是否大于0 require(msg.value > 0, "You need to send some Ether"); // 调用recipient地址对应的合约,并带有value个eth执行转账,无参数则传空 uint256 gasLimit = 3000; (bool result,) = recipient.call{value: msg.value, gas: gasLimit}(""); if (!result) { revert("Transfer Failed") } } }
转账失败
- Gas的消耗取决于转账操作执行到的阶段;成功与否gas都会损失;
- 如果转账未开始,或执行的操作较少时失败,仅消耗少量gas,剩余gas退还;
- 如果转账已经执行到fallback、receive函数,gas消耗视执行情况而定;
- call函数内如果设置了gas limit,因为gas不足而转账失败,则交易失败,gas不退还;