Solidity地址支付方法SendTransfer和Call的使用

Posted CamphorBloom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Solidity地址支付方法SendTransfer和Call的使用相关的知识,希望对你有一定的参考价值。

以上三种转账方式都属于地址的成员属性(members of address)。

参见地址成员类型

Transfer

如果当前合约的余额不够大或者 Ether转账被接收账户拒绝,转账功能将失败。接收方智能合约应定义回退函数,否则转账调用将引发错误。transfer函数在失败时恢复。另外它被硬编码以防止重入攻击(这句话不是很能理解)。

示例1:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract AddressFunction 
    function transfer(address payable _to) public payable 
        _to.transfer(msg.value);
    

测试

  

Send

Send是和Transfer具有同等功能的低级api。如果执行失败,当前合约不会因为异常而停止,但会返回false。

示例2:

    function send(address payable _to) public payable 
        bool isSend = _to.send(msg.value);
        require(isSend, "Send fail");
    

初看这段代码总会感觉怪怪的,一般思维调send方法不是发送方吗(solidity设计的某些api反人类),其实这里的_to指向的是接收方(包括transfer使用)。

这里为什么要加上payable关键字,它可以修饰地址和函数,使之具有接受和转账以太的功能。

贴一个官方文档的说明;

 测试

send与transfer都有2300gas的限制,msg.value可以为零。官方推荐在收款人取款的模式下,使用transfer更好,因为send需要不断对发送地址余额进行判断。

尝试转移大于发送地址余额的value,此时交易将一直处于pending状态....

transact to AddressFunction.send pending ... 

Call

这是将 ETH 发送到智能合约的推荐方式。空参数触发接收地址的回退功能(fallback function)。

示例3:

 function calls(address payable _to) public payable 

        (bool isSuccess, /* memory data */ ) = _to.callvalue: msg.value("");
        require(isSuccess, "Failure! Ether not send.");
    

测试

使用call,还可以触发合约中定义的其他功能,并发送固定数量的gas来执行该功能。交易状态作为布尔值发送,返回值在数据变量(bytes memory data)中发送。 

更具体使用的格式如下:

(bool sent, bytes memory data) = _to.callgas :10000, value: msg.value("func_signature(uint256 args)");

 2019年,solidity官方已经弃用了send和transfer,推荐call方法进行转账操作,但还是要小心使用官方给出了警告:

 

参考: https://medium.com/coinmonks/solidity-transfer-vs-send-vs-call-function-64c92cfc878a

            Types — Solidity 0.8.17 documentation 

solidity基础(支付ETH+发送ETH)

一、合约支付ETH


pragma solidity >=0.7.0 <0.9.0;

contract Payable
//payable关键词,函数可以接受以太坊主币的传入,否则传入会报错
    
    address payable public owner;//将地址标记为payable属性,地址就能发送以太坊主币
    constructor()
        owner=payable(msg.sender);
    
     //函数接受主币
     function desposit() external payable

     function getBalance() external view returns (uint)
         return address(this).balance;
     


二、合约发送ETH

有3种方式发送:
1.transfer 2300 gas ,失败会reverts
2.send 2300 gas,返回bool类型标记是否发送成功
3.call 剩余的所有gas, 返回bool和data数据

contract SendEther
//传入主币
constructor() payable 
receive() external payable 
//transfer
function sendViaTransfer(address payable _to) external payable
  _to.transfer(123);

//send
function sendViaSend(address payable _to) external payable
    bool sent=_to.send(123);
    require(sent,"send fail");

//call
function sendViaCall(address payable _to) external payable
   (bool success,)= _to.callvalue:123("");
    require(success,"call faild");

 
//接收主币的log
 contract EthReceiver
    event Log(uint amount,uint gas);
    receive() external payable
    emit Log(msg.value,gasleft());
  
  

以上是关于Solidity地址支付方法SendTransfer和Call的使用的主要内容,如果未能解决你的问题,请参考以下文章

第153篇 Solidity 中支付通道的实现

第153篇 Solidity 中支付通道的实现

《solidity学习笔记》chapter 2-solidity基础知识

代币(solidity)- 用户支付 gas 后,从主应用钱包中奖励用户 X 数量的代币

Solidity:TypeError:函数声明为视图,但此表达式修改了状态,因此需要不可支付(默认)或应付

执行智能合约时的 Solidity 错误消息:“如果您发送价值,则应支付被调用的函数......”