介绍了调用智能合约中"读方法"与"写方法"的区别
方法(函数)的分类
智能合约中的方法可以粗暴的分为两类:
- 不会改变虚拟机状态的方法
- 会改变虚拟机状态的方法
假设我们将他们称为"读方法"和"写方法", 那么读方法而言, 其是不会创建交易和花费GAS的, 是免费的. 对于写方法而言, 需要收取’手续费’进行挖矿的.
| 关键字 |
描述 |
改变虚拟机状态? |
| pure |
不读数据, 也不写数据 |
NO |
| view |
读数据, 但不写数据 |
NO |
| payable |
支付以太, 肯定写数据 |
YES |
| 未明确指示的 |
其它可能写数据的 |
YES |
Web3.js的 call() 与Send()
对于上面两类方法, Web3.js中分别对应Call方法和Send方法来进行调用
|
创建交易 |
改变虚拟机状态 |
| Call() |
NO |
NO |
| Send() |
YES |
YES |
实际上从语法层面上而言, 无论是读方法还是写方法, 都可以调用 call , 但对于写方法, 调用call虚拟机状态并不会改变, 并且不会报错.
举例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract temp {
int private counter;
function add() public {
counter ++;
}
function get() public view returns(int){
return counter;
}
}
|
调用代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
const base = require('./base');
const c = base.initContract('temp');
async function test(){
await c.methods.get().call().then(x=>{
console.log("current value:", x);
})
await c.methods.add().call()
await c.methods.get().call().then(x=>{
console.log("after call add(): current value:", x);
})
let accounts = await base.web3Instance.eth.getAccounts();
await c.methods.add().send({from: accounts[0], gas: 3000000})
await c.methods.get().call().then(x=>{
console.log("after send add(): current value:", x);
})
}
test()
|
输出
1
2
3
|
current value: 0
after call add(): current value: 0
after send add(): current value: 1
|
可以看到使用 call 调用 add()后 值并没有变, 而用 send调用add()后, 值被累加1
web3.py
web3.py 中对应的是 call()和transact()