Blockchain Learning (Solidity Function) [Day10-11 | 5.25-5.26]

function

basic concepts

function definition

  • Function definition syntax
function function_name(<parameter list>) <visibility> <state mutability>
    [ returns(<return type>)]{
        // 语句
    }
  • visibility
    • private: the function can only be called within the defined smart contract
    • internal: This function can be called inside the defined contract or from an inherited contract.
    • external: can only be called from outside the contract. If you want to call it from the contract, you must use this.
    • public: can be called from anywhere
  • state mutability
    • View: Functions declared with view can only read the state, but cannot modify it.
    • pure: Functions declared with pure can neither read nor modify state.
    • payable: A function declared with payable can accept ether sent to the contract. If not specified, the function will automatically reject all ether sent to it.
  • Example
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract SoldityTest{
        constructor(){}
        function getResult() public view returns(uint){
            uint a = 1;     // 局部变量
            uint b = 2;
            uint result = a+b;
            return result;
        }
    }

function call

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SolidityTest{
    constructor(){}

    function getResult() public pure returns(string memory){
        return integerToString(3);  // 调用函数 integerToString
    }

    // integerToString 函数定义
    function integerToString(uint _i)internal pure
        returns(string memory){
            if(_i == 0){
                return "0";
            }
            uint j = _i;
            uint len;
            while(j!=0){
                len++;
                j/=10;
            }
            bytes memory bstr = new bytes(len);
            uint k = len - 1;
            while(_i != 0){
                bstr[k--] = bytes1(uint8(48 + _i % 10));
                _i /= 10;
            }
            return string(bstr);
        }
}

return statement

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test{
    function getResult() public view returns(uint product,uint sum){
        uint a = 1;     // 局部变量
        uint b = 2;
        product = a*b;  // 使用返回参数返回值
        sum = a+b;      // 使用返回参数返回值

        // 也可以使用 return 返回多个值
        // return(a*b,a+b);
    }
}

function return value

  • The function return value can be named or anonymous.
  • You can assign a value by name or use return to return
  • Support multiple return values
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract funreturn{

    // 返回值可以有名字
    function returnTest() public view returns(uint mul){
        uint a = 10;
        return a;
    }

    // 可以直接为返回值赋值
    function returnTest2()public view returns(uint mul){
        mul = 10;
    }

    // 当给返回值赋值后,并且有多个 return,以最后的 return 为主
    function returnTest3() public view returns(uint mul){
        uint a = 10;
        mul = 100;
        return a;
    }  

    // 返回常量,自动匹配
    function returnTest4() public view returns(uint mul){
        uint a = 10;
        mul = 100;
        return 1;
    }

    // 函数可以有多个返回值,多返回值赋值
    function returnTest5(uint a,uint b)public view returns(uint add,uint mul){
        add = a+b;
        mul = a*b;
    }

    // 函数可以有多返回值,返回 return(param list)
    function returnTest6(uint a,uint b)public view returns(uint add,uint mul){
        return(a+b,a*b);
    }

    // 交换变量的值
    function returnTest7(uint a,uint b)public view returns(uint a1,uint b1){
        return(b,a);
    }
}
  • How to call a function with multiple return values
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract funreturn{
    // 定义多返回值函数
    function returnFunc() private pure returns(uint a,uint b){
        return(1,2);
    }

    // 调用多返回值函数
    function callFunc1() public pure returns(uint,uint){
        (uint r1,uint r2) = returnFunc();
        return (r1,r2);
    }
    
    // 调用多返回值函数,先定义变量
    function callFunc2() public pure returns(uint,uint){
        uint r1;
        uint r2;
        (r1,r2) = returnFunc();
        return(r1,r2);
    }

    // 调用多返回值函数,但只取第一个返回值
    function callFunc3() public pure returns(uint,uint){
        (uint r1,) = returnFunc();
        return(r1,100);
    }
}

pure function

  • Pure function (pure function) means that the function does not read or modify the state, that is, it does not operate on the data on the chain.
  • If the following statements exist in a function, they are considered read and the compiler will throw a warning
    • Read status variables
    • Access address(this).balance or <address>.balance
    • Access any block, transaction, msg and other reshuffle variables (msg.sig and msg.data allow reading)
    • Call any function that is not a pure function
    • Use an inline assembly containing specific opcodes
  • If an error occurs, pure functions can use the revert() and require() functions to revert potential state changes
  • Declared as a pure function, you can add the pure keyword in the function declaration
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test {
   function getResult() public pure returns(uint product, uint sum){
      uint a = 1; 
      uint b = 2;
      product = a * b;
      sum = a + b; 
   }

View function

  • The view function, also known as the view function, means that the function will only read the state and will not modify the state.
    • In other words, the view function will only read the data on the chain and will not modify the data on the chain.
  • If the following statements exist in a function, they will be considered modified status and the compiler will throw a warning
    • Modify state variables
    • trigger event
    • Create contract
    • use selfdestruct
    • Send Ether
    • Call any function that is not a view function or a pure function
    • Use underlying calls
    • Using an inline assembly that contains certain opcodes
  • The Getter method of the state variable defaults to the view function
  • Declared as a view view function, you can add the view keyword in the function declaration
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ViewDemo{
    uint factor = 2;    // 状态变量

    function getResult(uint num) public view returns(uint){
        uint result = num * factor;
        return result;

    /*  在这个例子中,函数getResult中,只是读取了状态变量factor的值,而没有修改它的值,所以这个函数是一个view函数。 */
    }
}

Constructor

  • The constructor is a special function that can only be called once when the contract is deployed, and cannot be called again afterwards.
    • Commonly used to initialize state variables
    • Use constructor as constructor
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test{
    uint a;

    // 不带参数的构造函数
    constructor(){
        a = 0;
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test{
    uint a;
    
    // 带参数的构造函数
    constructor(uint _a){
        a = _a;
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test {
   int public a ;
   address public owner;

   constructor(int _a) public{
     // 将部署者地址存储到owner变量
      owner = msg.sender;
    // 将参数_a存储到a变量
      a = _a;
   }    
}


function modifier

  • modifier is used to declare a function modifier
    • Common operations can be extracted and packaged as function modifiers to improve code reusability and coding efficiency.
    • The role of modifier is very similar to the aspect function of Java Spring. When it acts on a function, the logic in the modifier can be pre-executed before or after the function is executed to enhance its functionality.
    • modifier is often used to check certain preconditions before function execution
    • Modifier is a contract attribute that can be inherited and overridden by derived contracts.
  • Basic function modifier
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ModifierTest{
    bool public paused;
    uint public counter;

    function setPaused(bool _paused)external{
        paused = _paused;
    }

    modifier isNotPaused(){
        require(!paused);   // 检查前置条件,判断paused是否被设置,如果paused为true那么终止执行
        _;      // 执行被 isNotPaused 修饰的函数
    }

    function add() external isNotPaused(){
        counter++;
    }
}

/*    add函数被修改器isNotPaused修饰,所以先执行 require(!paused),检查前置条件,然后再执行add函数的代码。    */
  • _ role
    • There is a line of code in the function modifier that only has underscore_. We think that underscore_ represents the code of the modified function.
    • The underscore actually helps us mark the execution location of the function modified by the modifier.
  modifier isNotPaused(){
        require(!paused);   // 检查前置条件,判断paused是否被设置,如果paused为true那么终止执行
        _;      // 执行被 isNotPaused 修饰的函数
}

/* 下划线 _在 require(!paused) 后面,则被修饰函数 add 在此判断条件之后执行。 */
  • Function modifiers with parameters
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ModifierTest{
    bool public paused;
    uint public counter;

    function setPaused(bool _pasued) external{
        paused = _pasued;
    }

    modifier isNotPaused(uint x){
        require(x>10);  // 检查前置条件:判断x是否大于10,如果x大于或者等于10,那么终止执行
        _;              // 执行被 isNotPaused 修饰的函数
    }

    function add(uint x)external isNotPaused(x){
        counter++;
    }
}
  • Complex example
    • The classic application of function modifier is the Ownable contract in the OpenZeppelin library
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/*  Ownable 可以判断合约的调用者是否为当前合约的 owner
    从而避免其他人随意的调用一些合约的关键操作
    同时,owner 可以指定任何其他人为此合约新的 owner
    显然,只有当前 owner 才能指定其他人为新的 owner */

    contract Ownable{
        // 变量 owner 指定此合约的 owner
        address public owner;
        // 发布时间 - 此合约 owner 已经换人(此逻辑于 modifier 无关,可以忽略)
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

        // 构造函数 创建合约自动执行,初始化合约所有人为合约创建者
        constructor(){
            owner = msg.sender;
            
        }

        // 定义一个函数修改器
        modifier onlyOwner(){
            // 判断此函数调用者是否为 owner
            require(msg.sender == owner);
            _;
        }

        // owner 可以用此函数将 owner 所有权转换给其他人,显然此函数只有 owner 才能调用
        // 函数末尾加上 onlyOwner 声明,onlyOwner 正是上面定义的 modifier
        function transferOwnership(address newOwner) public onlyOwner{
            require(newOwner != address(0));
            emit OwnershipTransferred(owner, newOwner);
            owner = newOwner;
        }

    }
  • The transferOwnership function of the above contract is used by the owner to transfer ownership to other people.
    • So declare the onlyOwner modifier at the end, onlyOwner will be executed before transferOwnership is executed.
require(msg.sender == owner);
  • To ensure that the caller of this function is the owner, if not the owner, an exception will be thrown

function overloading

  • Function overloading means that multiple functions can be defined with the same function name in the same scope.
  • The parameters (parameter types or number of parameters) of these functions must be different. Just different return values ​​are not allowed.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test{
    function getSum(uint a,uint b)public pure returns(uint){
        return a+b;
    }
    function getSum(uint a, uint b,uint c)public pure returns(uint){
        return a+b+c;
    }
    function callSumWithTwoArguments() public pure returns(uint){
        return getSum(1, 2);
    }
    function callSumWithThreeArguments() public pure returns(uint) {
        return getSum(1, 2, 3);
    }
}

/*  首先单击 callSumWithTwoArguments 按钮,然后单击 callSumWithThreeArguments 按钮查看结果 */

Math functions

  • addmod(uint x,uint y,uint k) returns (uint),calculate(x+y)%k
    • Computations performed with arbitrary precision and not limited to 2^256 size
  • mulmod(uint x,uint y,uint k) returns (uint),calculate(x+y)%k
    • In calculations, penalties are performed with arbitrary precision and are not limited to size 2^256
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test{
    function callAddMod() public pure returns(uint){
        return addmod(4, 5, 3);
    }

    function callMulMod() public pure returns(uint){
        return mulmod(4, 5, 3);
    }
}

/*  首先单击callAddMod 按钮,然后单击 callMulMod 按钮查看结果 */

encryption function

  • kecckak256 (bytes memory) returns (bytes32) Compute the Keccak-256 hash of the input

  • sha256(bytes memory) returns (bytes32) Computes the SHA-256 hash of the input.

  • ripemd160(bytes memory) returns (bytes20) Computes the RIPEMD-160 hash of the input.

  • ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)

    • Recover the address associated with a public key from an elliptic curve signature, or return zero on error

    • The function parameters correspond to the signed ECDSA values:

      • r - the first 32 bytes of the signature

      • s - the second 32 bytes of the signature

      • v the last byte of the signature

    • This method returns an address

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test{
    function callKeccak256() public pure returns(bytes32 result){
        return keccak256("ABC");
    }
}

// 输出:0: bytes32: result 0xe1629b9dda060bb30c7908346f6af189c16773fa148d3366701fbaa35d54f3c8

Guess you like

Origin blog.csdn.net/BingjieDreams/article/details/130873818