跳转至

15.Function

函数

函数由关键字 function 声明,后面跟函数名参数可视范围状态可变性返回值的定义。函数可以定义在合约内部,也可以定义在合约外部。

  • function: 声明函数的固定关键字

  • fnName : 函数名,推荐小驼峰写法,更多参考: 合约编码规范 (TODO:)

  • <parameter list> : 参数列表(参数类型 + 参数名字)

  • <visibility>: 可见性

  • public:可以从合约内外访问。

  • external:仅可从合约外部访问。这个修饰符只能用于函数。

  • internal:只能从当前合约或从继承合约访问。

  • private:只能从当前合约访问。

在Solidity中,publicexternal是两种不同的函数修饰符,它们有以下区别:

  • public:使用public修饰符标记的函数可以从合约内外访问。这意味着它们可以在合约内部调用,也可以在合约外部通过合约地址调用。如果函数返回一个值,则该值将作为事务的一部分返回给调用方。如果函数没有返回值,则调用方只能确定事务是否成功。
  • external:使用external修饰符标记的函数只能从合约外部访问。这个修饰符只能用于函数。这意味着它们不能在合约内部直接调用,而必须通过合约地址调用。如果函数返回一个值,则该值将作为事务的一部分返回给调用方。如果函数没有返回值,则调用方只能确定事务是否成功。

因此,publicexternal的主要区别在于它们是否可以在合约内部直接调用。如果函数需要在合约内部调用,则应该使用public修饰符。如果函数只需要从合约外部调用,则应该使用external修饰符。

  • <state mutability>: 状态可变性

  • pure声明函数不会修改或读取任何状态变量,也不会与区块链交互。这意味着它只依赖于传递给函数的参数,而不依赖于合约的状态。这种函数可以被其他函数调用,而不需要发送事务。如果函数尝试修改状态变量或与区块链交互,则编译器会发出警告。

  • view:声明函数不会修改任何状态变量,但会读取状态变量。这意味着它只依赖于合约的当前状态,而不会修改它。这种函数可以被其他函数调用,而不需要发送事务。如果函数尝试修改状态变量或与区块链交互,则编译器会发出警告。
  • payable:声明函数可以接收以太币,并将其添加到合约的余额中。这种函数可以被其他地址发送以太币的事务调用。如果函数尝试修改状态变量或与区块链交互,则编译器会发出警告。
  • 不写 pure/view/payable 中任何一个:这意味着函数既可以读取也可以写入状态变量。这种函数可以被其他函数或地址调用,并且可以修改合约的状态。

Getter functions can be declared view or pure.

View function declares that no state will be changed.

Pure function declares that no state variable will be changed or read.

  • returns (<return types>):返回值和返回参数类型

  • 传参

  • 值类型

  • 引用类型(字符串,数组)

    • 默认是为calldata类型

    • 在Solidity中,函数参数可以是"memory"或"calldata"类型。

    "memory"类型表示参数值将在函数内部创建并存储在内存中,

    而"calldata"类型表示参数值将在函数调用期间从外部传入,并且只能读取而不能修改

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

contract FunctionIntro {
    /*
    external:仅在外部可见(仅可修饰函数)——就是说,仅可用于消息调用(即使在合约内调用,也只能通过 this.func 的方式)  
    internal:仅在内部可见。
    pure: 用于标识一个函数不会访问或修改合约的状态,并且不会与其他合约进行交互。
    view: 用于标识一个函数不会修改合约的状态。然而,“view”函数与“pure”函数的区别在于,“view”函数可以访问合约的状态,但不会修改它。
    */
    function add(uint256 x, uint256 y) external pure returns (uint256) {
        return x + y;
    }

    function sub(uint256 x, uint256 y) external pure returns (uint256) {
        return x - y;
    }
}

View and Pure Functions

Getter functions can be declared view or pure.

View function declares that no state will be changed.

Pure function declares that no state variable will be changed or read.

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

contract ViewAndPureFunctions {
    uint256 public num;

    function viewFunc() external view returns (uint256) {
        return num;
    }

    function pureFunc() external pure returns (uint256) {
        return 1;
    }

    uint256 public x = 1;

    // 不改变state variable
    function addToX(uint256 y) public view returns (uint256) {
        return x + y;
    }

    // 不读取不改变state variable
    function add(uint256 i, uint256 j) public pure returns (uint256) {
        return i + j;
    }
}

案例 Counter

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

contract Counter {
    uint256 public count;

    function inc() external {
        count += 1;
    }

    function dec() external {
        count -= 1;
    }
}

Constructor

only called once when the contract is deployed

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

// Base contract X
contract X {
    address public owner;
    uint256 public x;

    constructor(uint256 _x) {
        owner = msg.sender;
        x = _x;
    }
}

image-20230918165905960

image-20230918165929619

案例

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

// Base contract X
contract Ownable {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    // 创建function modifier, 只有owner才能call function
    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }

    function setOwner(address _newOwner) external onlyOwner {
        require(_newOwner != address(0), "invalid address");
        owner = _newOwner;
    }

    function onlyOwnerCanCallThisFunc() external onlyOwner {
        //
    }

    function anyOneCanCall() external {}
}

传参和返回值

函数可以有一个或者多个参数,也可以有一个或者多个返回值

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

// Base contract X
contract FunctionOutputs {
    // 传入多个参数,返回多个返回值
    // 可以只指定返回值类型,不指定名字
    function returnMany() public pure returns (uint256, bool) {
        return (1, true);
    }

    // 可以指定返回值名字
    function named() public pure returns (uint256 x, bool b) {
        return (1, true);
    }

    // 如果没有特别return,会返回指定的名字的参数的值
    function assigned() public pure returns (uint256 x, bool b) {
        x = 1;
        b = true;
    }
}

Visibility

在Solidity中,函数是执行特定任务的代码集。函数提供了智能合约中代码的可重用性。在Solidity中,使用function关键字定义函数。

image-20230925095612779

Solidity中的函数可见性定义了函数对合约内部或其他合约中其他函数的可见性。函数可见性有助于确定在合约或其他合约中可以使用哪些函数。它由智能合约的开发人员指定。Solidity中默认的变量可见性为internalSolidity中默认的函数可见性为public

image-20230925095645389