デプロイしたコントラクトを操作する@python
前回の記事でデプロイしたコントラクトを操作します。
mint
まずはmintしてみます。
#pnz.py
from web3 import Web3
from eth_abi import encode
from datetime import datetime
import json
my_wallet_address = 'my_wallet_address'
my_private_key = 'my_private_address'
PNZcontract = '0xE31cb151f3C9DF87738cEA3283bd99A12FfBde19'
#Web3のセットアップ(Unichain Sepolia)
w3 = Web3(Web3.HTTPProvider("https://sepolia.unichain.org"))
# コントラクトインスタンスの作成
with open('PNZ_ABI.json') as f:
PNZcontractABI = json.load(f)
pnz = w3.eth.contract(address=PNZcontract, abi=PNZcontractABI)
#トランザクションの作成(mint)
tx = pnz.functions.mint(my_wallet_address, 1).build_transaction({
'value': w3.to_wei(0, 'ether'),
'gas': 2000000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(my_wallet_address)
})
#トランザクションの表示
print(tx)
# トランザクションの署名と送信
signed_tx = w3.eth.account.sign_transaction(tx, private_key=my_private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
print('PNZ transaction')
print(w3.to_hex(tx_hash))
result = w3.eth.wait_for_transaction_receipt(tx_hash)
status = result['status']
if status == 1:
print('Transaction Succeeded')
else:
print('Transaction Failed')
同ディレクトリにPNZ_ABI.jsonというファイル名でABIファイルを置きました。
実行してみます。
python3 pnz.py
実際にmintされていればウォレット内にPNZトークンがあるはずですので確認してみます。
メタマスクのトークン追加でPNZトークンのコントラクトアドレスを入力すると、自動的にトークンシンボル:PNZ、トークンの少数桁数:18を認識してくれました。
1wei単位しか入っていませんでした。
なるほどdecimalが18なのでweb3.to_wei(1, 'ether')で引数入力する必要がありました。
コードの以下の部分を修正して再度実行してみます。
#トランザクションの作成(mint)
tx = pnz.functions.mint(my_wallet_address, w3.to_wei(1, 'ether')).build_transaction({
'value': w3.to_wei(0, 'ether'),
'gas': 2000000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(my_wallet_address)
})
今度はしっかりと1PNZありました。
get関数を呼んでみる。
・name()
・symbol()
・decimals()
・totalSupply()
・balanceOf()
・owner()
を呼んでみます。
#pnz_call.py
from web3 import Web3
from eth_abi import encode
from datetime import datetime
import json
my_wallet_address = 'my_wallet_address'
PNZcontract = '0xE31cb151f3C9DF87738cEA3283bd99A12FfBde19'
#Web3のセットアップ(Unichain Sepolia)
w3 = Web3(Web3.HTTPProvider("https://sepolia.unichain.org"))
#コントラクトインスタンスの作成
with open('PNZ_ABI.json') as f:
PNZcontractABI = json.load(f)
pnz = w3.eth.contract(address=PNZcontract, abi=PNZcontractABI)
#name()関数の呼び出し
name = pnz.functions.name().call()
print("name = " + name)
#symbol()関数の呼び出し
symbol = pnz.functions.symbol().call()
print("symbol = " + symbol)
#decimals()関数の呼び出し
decimals = pnz.functions.decimals().call()
print("decimals = " + str(decimals))
#totalSupply()関数の呼び出し
totalSupply = pnz.functions.totalSupply().call()
print("totalSupply = " + str(totalSupply))
#balanceOf()関数の呼び出し
balance = pnz.functions.balanceOf(my_wallet_address).call()
print("balance = " + str(balance))
#owner()関数の呼び出し
owner = pnz.functions.owner().call()
print("owner = " + owner)
思っていた結果となりました。
1つのウォレットで2回mintを行い、それぞれ数量が1、1*10^(18)ということでtotalSupplyは1000000000000000001となります。
また、mintしたアドレスでbalanceOf関数を使ったのでbalanceも同じ値になります。
これを別のアドレスを使って呼び出すと(my_wallet_addressを別のアドレスに変更すると)、totalSupplyは変わりませんが、balanceは0になりました。正しい動きをしています。
送金(transfer)してみる。
#pnz_transfer.py
from web3 import Web3
from eth_abi import encode
from datetime import datetime
import json
my_wallet_address = 'my_wallet_address'
other_wallet_address = 'other_wallet_address'
my_private_key = 'my_private_key'
PNZcontract = '0xE31cb151f3C9DF87738cEA3283bd99A12FfBde19'
#Web3のセットアップ(Unichain Sepolia)
w3 = Web3(Web3.HTTPProvider("https://sepolia.unichain.org"))
# コントラクトインスタンスの作成
with open('PNZ_ABI.json') as f:
PNZcontractABI = json.load(f)
pnz = w3.eth.contract(address=PNZcontract, abi=PNZcontractABI)
#トランザクションの作成(transfer)
tx = pnz.functions.transfer(other_wallet_address, w3.to_wei(0.3, 'ether')).build_transaction({
'value': w3.to_wei(0, 'ether'),
'gas': 2000000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(my_wallet_address)
})
#トランザクションの表示
print(tx)
# トランザクションの署名と送信
signed_tx = w3.eth.account.sign_transaction(tx, private_key=my_private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
print('PNZ transfer transaction')
print(w3.to_hex(tx_hash))
result = w3.eth.wait_for_transaction_receipt(tx_hash)
status = result['status']
if status == 1:
print('Transaction Succeeded')
else:
print('Transaction Failed')
成功しているかをbalanceOfで確認してみます。
#pnz_call.py
from web3 import Web3
from eth_abi import encode
from datetime import datetime
import json
my_wallet_address = 'my_wallet_address'
other_wallet_address = 'other_wallet_address'
PNZcontract = '0xE31cb151f3C9DF87738cEA3283bd99A12FfBde19'
#Web3のセットアップ(Unichain Sepolia)
w3 = Web3(Web3.HTTPProvider("https://sepolia.unichain.org"))
#コントラクトインスタンスの作成
with open('PNZ_ABI.json') as f:
PNZcontractABI = json.load(f)
pnz = w3.eth.contract(address=PNZcontract, abi=PNZcontractABI)
#name()関数の呼び出し
name = pnz.functions.name().call()
print("name = " + name)
#symbol()関数の呼び出し
symbol = pnz.functions.symbol().call()
print("symbol = " + symbol)
#decimals()関数の呼び出し
decimals = pnz.functions.decimals().call()
print("decimals = " + str(decimals))
#totalSupply()関数の呼び出し
totalSupply = pnz.functions.totalSupply().call()
print("totalSupply = " + str(totalSupply))
#balanceOf()関数の呼び出し
my_balance = pnz.functions.balanceOf(my_wallet_address).call()
print("my_balance = " + str(my_balance))
other_balance = pnz.functions.balanceOf(other_wallet_address).call()
print("other_balance = " + str(other_balance))
#owner()関数の呼び出し
owner = pnz.functions.owner().call()
print("owner = " + owner)
my_wallet_addressからother_wallet_addressに300000000000000000が送金できていることが分かります。
burnしてみる。
#pnz_burn.py
from web3 import Web3
from eth_abi import encode
from datetime import datetime
import json
my_wallet_address = 'my_wallet_address'
my_private_key = 'my_private_key'
PNZcontract = '0xE31cb151f3C9DF87738cEA3283bd99A12FfBde19'
#Web3のセットアップ(Unichain Sepolia)
w3 = Web3(Web3.HTTPProvider("https://sepolia.unichain.org"))
# コントラクトインスタンスの作成
with open('PNZ_ABI.json') as f:
PNZcontractABI = json.load(f)
pnz = w3.eth.contract(address=PNZcontract, abi=PNZcontractABI)
#トランザクションの作成(burn)
tx = pnz.functions.burn(w3.to_wei(0.1, 'ether')).build_transaction({
'value': w3.to_wei(0, 'ether'),
'gas': 2000000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(my_wallet_address)
})
#トランザクションの表示
print(tx)
# トランザクションの署名と送信
signed_tx = w3.eth.account.sign_transaction(tx, private_key=my_private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
print('PNZ burn transaction')
print(w3.to_hex(tx_hash))
result = w3.eth.wait_for_transaction_receipt(tx_hash)
status = result['status']
if status == 1:
print('Transaction Succeeded')
else:
print('Transaction Failed')
確認してみます。
想定通り、my_balanceとtotalSupplyが減少しています。
バグに気が付きました。
burn関数、バグがありますね・・・
こちら、msg.senderがburnしようとしている数量(value)以上のトークンを持っているのかどうかの確認が抜けていますね・・・
require(_balances[msg.sender] >= value, "insufficient balance");
これが必要かと思いました。
とはいえ、burnだから0になったら終わる?ということはこの確認は不要?
という疑問も残りました・・・
hello()を呼び出す。
何のことは無いですね。
#pnz_hello.py
from web3 import Web3
from eth_abi import encode
from datetime import datetime
import json
PNZcontract = '0xE31cb151f3C9DF87738cEA3283bd99A12FfBde19'
#Web3のセットアップ(Unichain Sepolia)
w3 = Web3(Web3.HTTPProvider("https://sepolia.unichain.org"))
#コントラクトインスタンスの作成
with open('PNZ_ABI.json') as f:
PNZcontractABI = json.load(f)
pnz = w3.eth.contract(address=PNZcontract, abi=PNZcontractABI)
#hello()関数の呼び出し
hello = pnz.functions.hello().call()
print(hello)
おまけ(保有数量以上burnしてみる)
思い切って2PNZをburnしてみます。
#pnz_burn.py
from web3 import Web3
from eth_abi import encode
from datetime import datetime
import json
my_wallet_address = 'my_wallet_address'
my_private_key = 'my_private_key'
PNZcontract = '0xE31cb151f3C9DF87738cEA3283bd99A12FfBde19'
#Web3のセットアップ(Unichain Sepolia)
w3 = Web3(Web3.HTTPProvider("https://sepolia.unichain.org"))
# コントラクトインスタンスの作成
with open('PNZ_ABI.json') as f:
PNZcontractABI = json.load(f)
pnz = w3.eth.contract(address=PNZcontract, abi=PNZcontractABI)
#トランザクションの作成(burn)
tx = pnz.functions.burn(w3.to_wei(2, 'ether')).build_transaction({
'value': w3.to_wei(0, 'ether'),
'gas': 2000000,
'gasPrice': w3.eth.gas_price,
'nonce': w3.eth.get_transaction_count(my_wallet_address)
})
#トランザクションの表示
print(tx)
# トランザクションの署名と送信
signed_tx = w3.eth.account.sign_transaction(tx, private_key=my_private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
print('PNZ burn transaction')
print(w3.to_hex(tx_hash))
result = w3.eth.wait_for_transaction_receipt(tx_hash)
status = result['status']
if status == 1:
print('Transaction Succeeded')
else:
print('Transaction Failed')
なんと、失敗しました。
保有数など確認してみます。
正常です・・・
今の私には何故かは理解できませんが、辻褄の合わないburnはrevertされるのかもしれません。
「バグに気が付きました」と書きましたが、もしかすると理屈を持って現状のように書くのが正しい?
また一つ勉強しないといけないことが増えました。