0%

solidity | 账户

solidity 的账户概念。

账户由 20 个字节组成,一般分为外部账户「EOA」和合约账户 「CA」。

两类账户可以交互,但是,只能由外部账户发起,并且 gas 由外部账户支付。

合约无法自己执行或者定时自己执行。

合约区分外部账户还是合约账户

我根据上面的参考资料写了一个合约。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
pragma solidity ^0.8.0;

contract Test {

constructor(
){}

function isContract(address account) public view returns (bytes32) {
bytes32 codehash;
assembly {
codehash := extcodehash(account)
}
return codehash;
}

function isContract2(address account) public view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}

function isContract3(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.

return account.code.length > 0;
}

function isContract4(address addr) public view returns (bytes32) {
bytes32 size;
assembly {
size := extcodehash(addr)
}
return size;
}
}

我在 bsc 的测试网进行了部署。

然后用 web3.py 进行了测试。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import time
from web3 import Web3

abi = """[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "isContract",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "isContract2",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "addr",
"type": "address"
}
],
"name": "isContract4",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
}
]
"""

w3 = Web3(Web3.HTTPProvider("https://data-seed-prebsc-1-s1.binance.org:8545"))
pancakeswap = "0xC73269f2C709F0a69435cd3582C1F35dff0cb44C"
contractObj = w3.eth.contract(
address=Web3.toChecksumAddress(pancakeswap), abi=abi)
data1 = contractObj.functions.isHuman(Web3.toChecksumAddress("0xeD47E52c570431cd2d45F63760661EaD68167f9D")).call()
data2 = contractObj.functions.isContract(Web3.toChecksumAddress("0xeD47E52c570431cd2d45F63760661EaD68167f9D")).call()
data3 = contractObj.functions.isContract2(Web3.toChecksumAddress("0xeD47E52c570431cd2d45F63760661EaD68167f9D")).call()

print(data1)
print(data2)
print(data3)
print(Web3.toText(data1))

感兴趣的可以自己找合约和普通账户测试一下。

ps: 为什么我要使用 测试网进行部署,而不是 ganache 进行本地模拟主网呢?

因为 ganache 非常不稳定,主要体现在

  • 调用方法,每次返回的值都不一样
    • 合约地址返回非合约地址的值
    • 部署同一份合约,然后查询同一个地址,返回的值都不一样
请我喝杯咖啡吧~