0%

solidity | python 如何和合约互动

虽然我很早就知道了,但是,有的时候长达好几个月不写合约,再写的话,有些细节总是忘记,然后还得进行测试,所以,有了这篇文章。

对所有细节做一个巩固。

相关的案例选择的是

前期知识

这里面主要是执行两个

  • 查询余额
  • mint

ABI 可以简写如

1
2
3
4
5
6
7
8
9
10
11
erc1155_abi = """
[{
"constant": true,
"inputs": [{"name": "who", "type": "address"},{"name":"id","type":"uint256"}],
"name": "balanceOf",
"outputs": [{"name": "", "type": "uint256"}],
"payable": false,
"stateMutability": "view",
"type": "function"
}]
"""

无验证互动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from web3 import Web3

abi = """[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"msg","type":"string"}],"name":"mathError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]"""

w3 = Web3(Web3.HTTPProvider("https://bsc.getblock.io/testnet/?api_key=5deb2510-62f9-40a9-b0e0-0039f9025ded"))

address = "0xeDD891059D0d87bE783C5914DBB8E80f273B7918"
contract = "0xd1693560A107B2E12F32e925FDe1867EC38FA3c6"

contract_ = w3.eth.contract(
address=Web3.toChecksumAddress(contract), abi=abi)

amount = contract_.functions.balanceOf(Web3.toChecksumAddress(address)).call()

print(amount)

有验证互动

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
from web3 import Web3

abi = """[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"msg","type":"string"}],"name":"mathError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]"""

w3 = Web3(Web3.HTTPProvider("https://bsc.getblock.io/testnet/?api_key=***"))

address = "0xD1B260aba3bA6f3D3099725b1b1C7cdD12581974"
contract = "0xd1693560A107B2E12F32e925FDe1867EC38FA3c6"
private = "***"

contract_ = w3.eth.contract(
address=Web3.toChecksumAddress(contract), abi=abi)


def encode_mint():
tx_dic = contract_.functions.mint(100). \
buildTransaction(
{
'gas': 500000,
}
)
return tx_dic


def send_transaction(tx_dic):
nonce = w3.eth.getTransactionCount(address)
tx_dic["nonce"] = nonce
tx_dic['gasPrice'] = w3.eth.gasPrice
sign_tx = w3.eth.account.signTransaction(tx_dic, private_key=private)
txn_hash = w3.eth.sendRawTransaction(sign_tx.rawTransaction)
return Web3.toHex(txn_hash)


def get_wait_receipt(tx):
data = w3.eth.waitForTransactionReceipt(tx)
return data


if __name__ == '__main__':
tx_dic = encode_mint()
tx = send_transaction(tx_dic)
data = get_wait_receipt(tx)
print(data)

但是,你也可以通过 HTTP 进行交互。

不知道 ABI 的交互,有验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def safe_transferFrom(address):
fromAddress = Web3.toChecksumAddress(address)
nonce = w3.eth.getTransactionCount(fromAddress)
transaction = {
'from': fromAddress,
'to': contract,
'gas': 241838,
'gasPrice': w3.toWei('2.5', 'gwei'),
'nonce': nonce,
'data': "f242432a000000000000000000000000" + "A26Dd9C8963a4D8940a88f01f0bF7E4d0E471aE5" + "000000000000000000000000" + "d7b95db09d7d9dac7ca86487fc2c7a570250bf20" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
'chainId': 84531
}
signed_tx = w3.eth.account.signTransaction(transaction, private)
txn_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(f"nonce: {nonce}")
return Web3.toHex(txn_hash)

上面的例子来自于

其对应的方法是

写一个和合约交互,然后转账。

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
import time

from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://bsc-mainnet.nodereal.io/v1/***"))


def send_bnb(last_address, last_private, address):
# 转账
balance = w3.eth.get_balance(last_address)
nonce = w3.eth.getTransactionCount(last_address)
gas = w3.eth.estimateGas({'from': last_address, 'to': address, 'value': balance})
value = balance - gas * w3.toWei('3.1', 'gwei')
transaction = {'from': last_address,
'to': address,
'nonce': nonce,
'gasPrice': w3.toWei('3', 'gwei'),
'gas': gas,
'value': value,
'data': ''}

signed_tx = w3.eth.account.signTransaction(transaction, last_private)
txn_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(f"\t\t{last_address} 向 {address} 转移 BNB {value} tx 为 {Web3.toHex(txn_hash)}")
# 查询是否到账
while 1:

balance = w3.eth.get_balance(address)

if balance > 0:
print(f"\t\t转移成功")
break

time.sleep(2)


def get_account():
account = w3.eth.account.create()
print(f"\t生成新地址: {account.address} 私钥: {account.key.hex()}")
return account.address, account.key.hex()


def safe_transferFrom(key, secret, contract):
fromAddress = Web3.toChecksumAddress(key)
nonce = w3.eth.getTransactionCount(fromAddress)
transaction = {
'from': fromAddress,
'to': Web3.toChecksumAddress(contract),
'gas': 241838,
'gasPrice': w3.toWei('3', 'gwei'),
'nonce': nonce,
'data': "1249c58b",
}
signed_tx = w3.eth.account.signTransaction(transaction, secret)
txn_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(f"地址: {key} 私钥: {secret} 相关的 tx 为 {Web3.toHex(txn_hash)}")


if __name__ == '__main__':

last_address = ""
last_private = ""
contract = "0x02eE204dED463755FEa1774862881bA8b2Ce66a7"

while 1:
safe_transferFrom(last_address, last_private, contract)
time.sleep(10)
address, private = get_account()
send_bnb(last_address, last_private, address)
last_address = address
last_private = private
请我喝杯咖啡吧~