デプロイしたコントラクトを操作する@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
soneiumの文言は修正忘れです、お気になさらず

実際に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されるのかもしれません。
「バグに気が付きました」と書きましたが、もしかすると理屈を持って現状のように書くのが正しい?

また一つ勉強しないといけないことが増えました。


いいなと思ったら応援しよう!