見出し画像

Web3.pyによるトークンコントラクト呼び出し(BSC)~残高確認,送金,承認~

納豆男爵です。この記事ではトークンのコントラクトに関する情報をまとめていきます。BSCのトークンのコントラクトをWeb3.pyから呼び出す方法をサンプルコード付きで解説します。
最低限の下準備として、Pythonの実行環境とWeb3.pyのインストール、ウォレット情報の準備が必要です。これらを実施できていない方は「超簡単! PythonによるBSC DeFi bot作り① ~送金する~」をまずは読んでいただくことをお勧めします。

他の記事との重複部分が多いですが、本記事では以下のような内容を含みます。

1. トークンコントラクトを呼び出すための下準備

トークンコントラクトをWeb3.pyから呼び出すためにはまず①トークンのコントラクトアドレス②コントラクトのABIを準備する必要があります。

① トークンのコントラクトアドレス

トークンのコントラクトアドレスを取得する際には、誤ったアドレスを掴まないように注意してください。ブロックチェーンにおいて自由に発行できるトークンは名前の重複を制限する仕組みなどはないため、トークンの名前だけからアドレスを探すと誤ったアドレスにたどり着くことがあります。

最も良い方法はプロジェクトのWebサイトからコントラクトアドレスを取得することです。例えばPancakeSwapで発行されているCAKEトークンの場合、PancakeSwapのサイトのメニューから「Docs」を選択し、ドキュメントサイトから「TOKENOMICS > CAKE」を選ぶとCAKEトークンに関する解説ページを見ることができます。これを見るとCAKEトークンのコントラクトアドレスが記載されています。
他にもトークン情報を閲覧するサービスから見つけるという方法があります。例えばCoinGeckoCAKEトークンのデータを見ることができますが、ここに「コントラクト」としてコントラクトアドレスが記載されているのを見ることができます。(いずれも2022年2月現在)
最もお勧めしない方法はBscScanで全トークンから検索を行う方法です。トークン一覧のページから検索クエリにCAKEと入れるとCAKEと名の付く多数のトークンが検索結果として得られます。CAKEトークンは時価総額が同等の同名トークンはないため、簡単に見つけられますがいわゆる草コインの場合はこの方法では見分けがつきません。気を付けましょう。

画像1

上の画像がBscScanからトークン名で検索する際の検索窓です。ここに名前を入れると検索できますが、お勧めしません

② トークンコントラクトのABI

さて、コントラクトアドレスが得られたら次はABIを取得していきます。ABIはBscScanから取得することができます。まずは取得したコントラクトアドレスをBscScanで開きましょう。CAKEトークンの場合は、コントラクトアドレスが0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82なので、BscScanのURLはhttps://bscscan.com/address/0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82となります。このURLのアドレス部分を変えても良いですし、BscScanのサイトで検索ボックスにコントラクトアドレスを入れても対象のページに飛ぶことができます。以下のようにコントラクトアドレスが示されたページが開けばOKです。

画像3

コントラクト情報が見れたら次はABIの取得です。上の図のように「Contract」と書かれたタブをクリックし、下の方にスクロールしていくと、下の図のように「Contract ABI」と書かれた領域があります。ここに記載されているのがABIです。コントラクトに設定された関数の入出力について列挙されています。これをjsonファイルとして保存しましょう。図の赤枠で示されたABIの右上に設置されたコピーボタンを押し、メモ帳等のテキストエディタを開いてこれを貼り付けましょう。貼り付けたらそれとわかるようなファイル名を付けて保存します。例えばCAKEトークンの場合は、"CAKE_Token_Contract_ABI.json" のようなファイル名が良いでしょう。これを作業用のフォルダに格納したらABIの取得は完了です。

画像3

準備作業の最後として、Web3.pyからトークンコントラクトのインスタンスを作ってみましょう。コントラクトの関数を呼び出すための準備をするだけなので以下のコードを動かしても何も起きません。エラーが発生しなければひとまずOKです。
ちなみに、BSCのトークンの主たる機能はだいたい同じです。該当トークンのABIを取得するのがベストですが、例えばCAKEのABIを他のトークンに適用しても特に問題ないことが多いです。

import json
from web3 import Web3

# RPCは有効なものであれば下記である必要はありません。
bsc_rpc = "https://bsc-dataseed.binance.org/"

# 対象のトークンコントラクトアドレスは適宜書き換えてください。
CAKE = '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82'

web3 = Web3(Web3.HTTPProvider(bsc_rpc))

# ABIを保存したファイル名も適宜書き換えてください。
with open('CAKE_Token_Contract_ABI.json') as f:
  cakeABI = json.load(f)

cakeContract = web3.eth.contract(address=CAKE, abi=cakeABI)

2. サイン不要の関数

続いては、上記設定したコントラクトを利用して、いくつかの関数を呼んでいきましょう。BSCのTokenにどのような関数が存在しているかはBscScanで見ることができます。改めてCAKEトークンのコントラクト情報を見てみましょう。

画像4

「Contract」タブの下に「Read Contract」と「Write Contract」のボタンがありますが、これらを押すと呼び出せる関数の一覧をみることができます。「Read Contract」がサイン不要、すなわちウォレットを接続することなく呼び出せる関数です。ガス代もかかりません。一方で「Write Contract」にあるのはサインが必要、すなわちウォレットを接続してガス代を払って実施する関数となります。ガス代はブロックチェーンへの書き込みに応じて発生するものですので、Read Contractはトークンの残高等のステータスに何らの影響を与えない関数一覧であり、Write Contractの方はトークンの状態に何らかの影響を与える関数一覧と見ることもできます。
まずは、Read Contractの関数を見ていきます。BscScanでいくつかの関数が見えていますが、そのうち以下を解説しましょう。
2.1 allowance
2.2 balanceOf
2.3 decimals
2.4 symbol

 2.1 allowance

いきなりやや難しい関数ですが、直訳すると許容量という意味です。対象のトークンがあるアドレスから別のアドレスへ支払われる際の許容量を示しています。PancakeSwap等でトークンをスワップする際にApproveという処理をすると思いますが、allowanceはこのトークンがどの程度Approveされているかを確認する関数ということになります。1番目の引数に支払元のアドレス、2番目の引数に支払先のアドレスを入れます。早速動きを確認してみましょう。

import json
from web3 import Web3

bsc_rpc = "https://bsc-dataseed.binance.org/"
walletAddress = '*** 対象ウォレットのアドレス ***'
pcsRouter = '0x10ED43C718714eb63d5aA57B78B54704E256024E' #PancakeSwap Routerコントラクト
CAKE = '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82'

web3 = Web3(Web3.HTTPProvider(bsc_rpc))

with open('CAKE_Token_Contract_ABI.json') as f:
   cakeABI = json.load(f)

cakeContract = web3.eth.contract(address=CAKE, abi=cakeABI)

# allowance関数の呼び出し
allowedAmount = cakeContract.functions.allowance(walletAddress, pcsRouter).call()

# 結果の表示
print('CAKE Allowance \n from\t{} \n to\t{} \n amount\t{}'.format(
 walletAddress,
 pcsRouter,
 web3.fromWei(allowedAmount,'ether')))

上記のコードでは支払先にPancakeSwapのルーターコントラクトを設定してみました。普段使いしているウォレットがあれば色々とApproveしているかと思います。私のウォレットでCAKEのallowanceを調べると以下のような出力が得られました。とっても大きい値が得られたので無制限のApproveがされているようです。

CAKE Allowance 
 from	[*** Wallet Address ***] 
 to	0x10ED43C718714eb63d5aA57B78B54704E256024E 
 amount	115792089237316195423570985008687907853269984665640564039457.584007913129639935

allowance関数から得られる返り値はwei単位であることに注意しましょう。CAKEトークンの場合は10^18で割ると一般的な枚数単位に変換することができます。web3.pyではfromWei関数を使って簡単に枚数単位(ether単位と呼ぶ)に変換できます。

 2.2 balanceOf

これは残高確認の関数です。ウォレットアドレスを指定して該当のトークンをどれだけ持っているか確認できます。引数はウォレットアドレスだけなので簡単ですね。

import json
from web3 import Web3

bsc_rpc = "https://bsc-dataseed.binance.org/"
walletAddress = '*** 対象ウォレットのアドレス ***'
CAKE = '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82'

web3 = Web3(Web3.HTTPProvider(bsc_rpc))

with open('CAKE_Token_Contract_ABI.json') as f:
     cakeABI = json.load(f)

cakeContract = web3.eth.contract(address=CAKE, abi=cakeABI)

# balanceOf関数の呼び出し
cakeBalance = cakeContract.functions.balanceOf(walletAddress).call()

print('CAKE Balance: {}'.format(web3.fromWei(cakeBalance,'ether')))

こちらも返り値はwei単位なのでfromWei関数を使ってわかりやすく変換してあげると良いです。上記のコードを動かすと以下のような出力が得られます。

CAKE Balance: 2

 2.3 decimals

この関数ではトークンのdecimals情報を得ることができます。これはトークンをどこまで細かい単位で取引できるか、という設定項目で、decimalsが18の場合には10のマイナス18乗(0.000000000000000001)を最小単位としてトークンのやり取りができることを意味しています。先ほどのbalanceOf等で出力される数字は、この最小単位がいくつあるかということを表しており整数で管理されます。fromWei関数等を使うとether単位に変換できるのですが、これはdecimalsが18の場合だけです。例えばdecimalsが9であった場合、balanceOfの出力をetherに直す場合は10^9で割る必要があります。ほとんどの健全なトークンはdecimalsが18なのですが、そうでない場合への対応を考える際にここを確認する必要があります。

import json
from web3 import Web3

bsc_rpc = "https://bsc-dataseed.binance.org/"
CAKE = '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82'

web3 = Web3(Web3.HTTPProvider(bsc_rpc))

with open('CAKE_Token_Contract_ABI.json') as f:
    cakeABI = json.load(f)

cakeContract = web3.eth.contract(address=CAKE, abi=cakeABI)

# decimals関数の呼び出し
dec = cakeContract.functions.decimals().call()

print('CAKE Decimals: {}'.format(dec))

サンプルは上記のようになりますが、引数もないのでただ呼ぶだけですね。上記のコードを動かすと以下のような出力が得られます。

CAKE Decimals: 18

 2.4 symbol

これもただ呼ぶだけで引数なしですが、トークンシンボルを得ることができます。トークン名を適応的に表示する場合に便利かもしれません。

import json
from web3 import Web3

bsc_rpc = "https://bsc-dataseed.binance.org/"
unknownToken = '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82'

web3 = Web3(Web3.HTTPProvider(bsc_rpc))

with open('CAKE_Token_Contract_ABI.json') as f:
   tokenABI = json.load(f)

tokenContract = web3.eth.contract(address=unknownToken, abi=tokenABI)

# symbol関数の呼び出し
ticker = tokenContract.functions.symbol().call()

print('Symbol of contract {}\n => {}'.format(unknownToken, ticker))

名称不明なコントラクトアドレスからトークン名を表示することができます。上記のコードを動かすと以下のような出力が得られます。

Symbol of contract 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82
 => Cake

3. サインが必要な関数

続いてサインが必要な関数(BscScanにおける「Write Contract」)を見ていきましょう。BscScan上は色々関数がありますが、一般的に使われるのはapprovetransferの2つです。increaseAllowance, decreaseAllowanceなんていうのもあるようですが、approveが使えれば十分です。

 3.1 approve

先ほど確認したallowanceを設定するための関数です。すなわち、自身のアドレスからあるアドレスへ支払うことのできる許容量を設定します。第1引数に支払先アドレス、第2引数にトークンの量を設定します。サンプルコードを見てみましょう。このサンプルでは支払先にPancakeSwapのルーターコントラクトを設定しています。他のコントラクトに対してトークンを支払う必要がある場合には、適宜支払先のコントラクトアドレスを変更してください。

ここから先は

7,433字

¥ 490

この記事が気に入ったらサポートをしてみませんか?