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