solidity函数

文章目录

前言

一、函数可见性visility
        1.public
        2.private
        3.external
        4.internal
二、函数状态易变性mutability
        1.view
        2.pure
        3.payable
        4.non-payable
三、函数修改器modifiy(类似python的装饰器、js的@decorator)
四、函数returns

五、receive&fallback是什么?

六、构造函数和析构函数

七、返回值

八、call函数

九、函数类型变量
总结


前言

1.定义函数:有函数体{}

2.声明函数,没有函数体{}

3.声明函数变量:function (uint) external returns (uint) name;

solidity函数结构:
function function_name( ) (modifiy) (virtual)[returns()]{ ... }
              不能数字开头       uint                                         public        view                        returns(uint, value_name){... no return,因为外面参数有}

                                           int                                           private       pure                        returns (return_type)        {...  return}            

                                           string                                      external       payable                          

                                           address                                  internal       none(不用写)              

                                           array                                                          none(不用写)             


一、函数可见性visiblity

函数的可见性有四种:

  • Private(私有):限制性最强,函数只能在所定义的智能合约内部调用。
  • Internal(内部):可以在所定义智能合约内部调用该函数,也可以从继承合约中调用该函数。
  • External(外部):只能从智能合约外部调用。 (如果要从智能合约中调用它,则必须使用 this。)
  • Public(公开):可以从任何地方调用 (最宽松)。对于公共状态变量,会生成自动getter函数。

public 和external类型函数有一个熟悉 selector

function f() internal view returns (bytes4) {

        return this.f.selector;

   }

solidity函数_第1张图片

二、函数状态可变性(mutability)

函数的可见性有四种:

  • view:用view声明的函数只能读取状态,而不能修改状态。
  • pure:用pure声明的函数既不能读取也不能修改状态。
  • payable:用payable声明的函数可以接受发送给合约的以太币,如果未指定,该函数将自动拒绝所有发送给它的以太币。
contract trans{
    
    uint256 public value;
    
    constructor() payable{
        value = msg.value;
    }
    
    function number()public view returns(uint256){
        return value;
    }
    
    function n()public payable returns(uint256){
        value = msg.value;
        return msg.value;
    }
}
  • non-payable:不用写任何内容
contract SimpleStorage {
     uint256 private data;
     
     function getData() external view returns(uint256) {
         return data;
     }     
    
     function setData(uint256 _data) external {
        data = _data;
     }
}

三、函数修饰符modifiy

3.1当你要在执行函数之前检查某些条件时,可以使用修饰器。例如,如果你要检查发件人是否是合约的所有者,则可以编写以下内容:

function selectWinner() external {
    require(msg.sender == owner, "this function is restricted to the owner);
    ...}

3.2使用修饰器,我们可以分离该代码,以便我们可以将其与其他函数复用,我们只需要声明修饰器,如下所示:

modifier onlyOwner(){
   require(msg.sender == owner, "this function is restricted to the owner);
  _; // will be replaced by the code of the function
     return 10;
}

然后将修饰器名称添加到函数中:

// 如果函数修改器onlyOwner中 _;后面还有语句,就接着执行

function selectWinner() external onlyOwner {
    return 7; 
    // 如果函数修改器onlyOwner中 _;后面还有语句,就接着执行 return 10;


   
    }

多重modifier的执行顺序,很重要!!!

solidity函数_第2张图片

四、函数返回值returns

函数可以返回任意数量的值作为输出。有两种方法从函数返回变量:

1. 使用返回变量名:

function arithmetic(uint _a, uint _b) public pure
        returns (uint o_sum, uint o_product)
    {
        o_sum = _a + _b;
        o_product = _a * _b;
    }
 

2. 直接在return语句中提供返回值:

function arithmetic(uint _a, uint _b) public pure
        returns (uint o_sum, uint o_product)
    {
        return (_a + _b, _a * _b);
    }
 

五、receive&fallback是什么?

合约最多可以具有一个fallback函数(一般翻译为回退函数)。这个函数不能有参数,不能返回任何参数,并且必须具有external可见性。如果其他函数均不匹配给定的函数签名,或者根本没有提供任何数据并且没有receive函数,则在调用合约时执行该函数。

5.1receive,往合约地址发送eth,成功,调用receive。

当向合约发送Ether且未指定调用任何函数(calldata 为空)时执行。这是在普通的以太坊转账上执行的函数(例如,通过.send().transfer()转账)。

receive() external payable{}

5.2fallback,

fallback() external payable{}

fallback函数特点:

不能有返回值。

合约最多可以具有一个fallback函数(一般翻译为回退函数)。这个函数不能有参数,不能返回任何参数,并且必须具有external可见性。如果其他函数均不匹配给定的函数签名,或者根本没有提供任何数据并且没有receive函数,则在调用合约时执行该函数。

5.2.1 当给合约转以太币时,必须有payable回退函数。

5.2.2 当调用合约不存在的函数时,就会掉用回退函数

// SPDX-License-Identifier:MIT
pragma solidity ^0.8.0;
 
contract ReceiveEther {
 
   string public data;

   receive() external payable {
       data = "receive call";
   }

   fallback() external payable {
       data = "fallback call";
   }

   function getBalance() public view returns (uint){
       return address(this).balance;
   }
}

fallback在接收以太币时,仅有2300gas来执行,下面操作会失败,因为消耗大于2300gas:

1.写存储(storage)
2.创建一个合约
3.执行外部(external)函数调用,会花费非常多的gas
4.发送ether

FallBack函数的实用场景
场景一:空投
利用FallBack函数,用户只需要使用钱包向空投合约发送0金额的转账(只消耗手续费),空投合约就可以向该地址进行空投。

场景二:锁仓
用户使用钱包将代币转账到锁仓合约中,锁仓合约利用FallBack函数接收到请求,就可以执行锁仓逻辑了。

六、构造函数和析构函数

构造函数 constructor

析构函数deconstructor(0.5以下版本才有):kill,生命周期结束时释放内存,

pragma solidity ^0.4.13;
// construct构造函数和析构函数
contract MyCoin{
    uint public amount;
    address owner;
    
    constructor(uint _data) public{
        amount=_data;
        owner=msg.sender;
    }
    
    function getBalance() public view returns (uint){
        
        return amount;
        
    }
    
    function kill() public{ // 析构函数
        if(owner==msg.sender){
            selfdestruct(owner);
        }
    }
}

七、返回值

// 函数可以返回多个值
function multipleReturns() returns(uint a, uint b, uint c) {
  return (1, 2, 3);
}

// 同时接收所有返回值
function processMultipleReturns() {
  uint a;
  uint b;
  uint c;
  // 这样来做批量赋值:
  (a, b, c) = multipleReturns();
}

//只接收部分返回值:或者如果我们只想返回其中一个变量:
function getLastReturnValue() {
  uint c;
  // 可以对其他字段留空:
  (,,c) = multipleReturns();
}

八、call函数,

lowlevel底层通信,合约之间根据address调用方法

pragma solidity ^0.4.0;
// call函数 call()是一个底层的接口,用来向一个合约发送消息[1],也就是说如果你想实现自己的消息传递,可以使用这个函数。
// 函数支持传入任意类型的任意参数,并将参数打包成32字节,相互拼接后向合约发送这段数据。
contract Person{
    uint age = 10;
    string public data;
    function increaseAge(string memory name, uint num) public returns (uint){
        string memory name2 = name;
        uint num2 = num;
        return ++age;
    }
    
    function getAge() public view returns (uint){
        return age;
    }

    function() external  {
       data = "fallback call";
    }
}

contract CallTest{
    
    function callByFun(address addr) public returns (bool){
        // bytes4 methodId = bytes4(keccak256("increaseAge(string,uint256)"));
        // return addr.call(methodId,"jack", 1); 

        // 下面这句等于上面2行
        return addr.call(abi.encodeWithSignature("increaseAge(string, uint256)","jack",2));
    }
    function callData(address addr) public returns (bool){
        return addr.call("abc", 256); // 找不到abc函数,会调fallback函数
    }
}

  • call: 最常用的调用方式,调用后内置变量 msg 的值会修改为调用者,执行环境为被调用者的运行环境(合约的 storage)。
  • delegatecall: 调用后内置变量 msg 的值不会修改为调用者,但执行环境为调用者的运行环境。
  • callcode: 调用后内置变量 msg 的值会修改为调用者,但执行环境为调用者的运行环境。

九、函数类型变量

pragma solidity ^0.4.18;

contract TestFunc {

  function a(uint x) external returns (uint z) {
    return x * x;
  }

  function b(uint x) external returns (uint z) {
    return 2 * x;
  }

  //  变量f 可以被赋值为函数a 或 函数b
  function select(function (uint) external returns (uint) f, uint x) external returns (uint z) {
     return f(x);
  }

  // 函数作为返回值的类型
  function getfun() public view returns (function (uint) external returns (uint) ) {
      return this.b;
  }


  function callTest(bool useB, uint x) external returns (uint z) {
    // 变量f 可以被赋值为 函数a 或 函数b
    function (uint) external returns (uint) f;
    if (useB) {
        f  = this.b;
    } else {
        f = this.a;
    }
    return f(x);
  }


  // 0x26121ff0
   function f() public view returns (bytes4) {
        return this.f.selector;
   }

}


总结

solidity函数结构:
function function_name( ) [returns()]{ ... }
              不能数字开头       uint                                         public        view                        returns(uint, value_name){... no return}

                                           int                                           private       pure                        returns (return_type)        {...  return}            

                                           string                                      external       payable                          

                                           address                                  internal       none(不用写)              

                                           array                                                          none(不用写)         

你可能感兴趣的:(solidity,笔记,js学习,p2p,网络协议,网络)