Input Dataを利用してABIが分からないコントラクトのトランザクションを通す@python
今回はKaiaネットワークです。
KaiaSwapにて0.001WKLAYをUSDC.eにスワップして、このトランザクションをもとにpythonでスワップコードを書こうとしたのですが、ABIが見つけられず、Input Dataに若干の手を加えてpythonコードで通した、という話です。
KaiaSwapでのトランザクション(コントラクトのABIが見つからない)
0.001WKLAYをUSDC.eにスワップする操作を何回かしたときのスクショを添付します。


それぞれのトランザクションをブロックエクスプローラで確認。
通常は、ここからコントラクトのページへ行き、ABIを拾ってこればpythonコードを書ける。
しかし、(少なくとも私は)コントラクトのABIにたどり着くことができなかった。
Input Dataを考察する
ABIが見つからないので、ゼロからInput Dataを構築することもできなければ、Input Dataをデコードすることもできない。
ならば、Input Dataをそのまま投げればトランザクションは通るのではないか?と考えた。
#0.001wklay_usdce.py
import json
from web3 import Web3
from datetime import datetime
baseRpc = "https://public-en.node.kaia.io"
walletAddress = 'my_wallet_address'
walletKey = 'my_private_key'
kaiaSwap = '0xc0ac932cac7b4d8f7c31792082e2e8f3cfe99c10'
web3 = Web3(Web3.HTTPProvider(baseRpc))
now = int(datetime.now().timestamp())
nonce = web3.eth.get_transaction_count(walletAddress)
tx = {
'value': web3.to_wei(0, 'ether'),
'chainId': 8217,
'gas': 20000000,
'gasPrice': web3.eth.gas_price,
'nonce': nonce,
'from': walletAddress,
'to': web3.to_checksum_address(kaiaSwap),
'data': '0x88d527dc000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000f69fd1acae36de01e61e722cdf44b5bf9baadd5c00000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000000000000000000012100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000067570e8b000000000000000000000000000000000000000000000000000000000000002b19aac5f612f524b754ca7e7c41cbfa2e981a44320001f4e2053bcf56d2030d2470fb454574237cf9ee3d4b000000000000000000000000000000000000000000'
}
print("tx = ")
print(tx)
signedTx = web3.eth.account.sign_transaction(tx, walletKey)
txHash = web3.eth.send_raw_transaction(signedTx.raw_transaction)
print('kaiaSwap transaction')
print(web3.to_hex(txHash))
result = web3.eth.wait_for_transaction_receipt(txHash)
status = result['status']
if status == 1:
print('Transaction Succeeded')
else:
print('Transaction Failed')
data部分に、下記のトランザクションのInput Dataをそのまま入れてみた。

通った・・・
ブロックエクスプローラでも。
しかし、時間が経つと失敗するようになる。
ここで、Input Dataの構造を思い出す。
deadlineという引数を取る場合もあると・・・
何度か実施した同様のスワップ(0.001WKLAY→USDC.e)のInput Dataを並べてみる。




argの7行目にdeadlineぽい数字が並んでいるのに気が付く。
ここを大きく設定してしまえば、トランザクションの有効期限が伸びる。
ただ、それ以外にもargの5行目と9行目も異なる場合があることに気が付く。
KaiaSwapのWebサイトからスワップしてInput Dataを確認して、という作業を繰り返していると、
・5行目はだんだんと値が小さくなる
・9行目はfee?が0.3%のときと0.05%のときで異なる
ということに気が付いた。
つまり、9行目は常に2択で、5行目は値を小さく設定し、7行目は値を大きく設定すればよいことが分かった。
トランザクションを通す
執筆現在は0.05%のパターンなのでInput Dataがこれに該当する方を選ぶ。

そして、まずは過去のInput Dataをそのまま通そうとしてみるが、通らない(deadline:有効期限)切れ。

では、上記txのdeadline部分:67570d07を69570d07に変えてみる。

しかし、通らない。何を意味しているかは分かりませんが5行目が時間とともに変化(小さくなっていく)からです。実際、5行目が変化しない時間間隔であればdeadlineを大きく設定するだけでトランザクションは通りました。
それでは、上記txの121の部分を000に変えてみます。

通りました。
ブロックエクスプローラでの確認は以下です。
fee?が0.3%のパターンのときも同様にできます。
最後にpythonコードを載せておきます。
#0.001wklay_usdce.py
import json
from web3 import Web3
from datetime import datetime
baseRpc = "https://public-en.node.kaia.io"
walletAddress = 'my_wallet_address'
walletKey = 'my_private_key'
kaiaSwap = '0xc0ac932cac7b4d8f7c31792082e2e8f3cfe99c10'
web3 = Web3(Web3.HTTPProvider(baseRpc))
now = int(datetime.now().timestamp())
nonce = web3.eth.get_transaction_count(walletAddress)
tx = {
'value': web3.to_wei(0, 'ether'),
'chainId': 8217,
'gas': 20000000,
'gasPrice': web3.eth.gas_price,
'nonce': nonce,
'from': walletAddress,
'to': web3.to_checksum_address(kaiaSwap),
'data': '0x88d527dc000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000f69fd1acae36de01e61e722cdf44b5bf9baadd5c00000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000069570d07000000000000000000000000000000000000000000000000000000000000002b19aac5f612f524b754ca7e7c41cbfa2e981a44320001f4e2053bcf56d2030d2470fb454574237cf9ee3d4b000000000000000000000000000000000000000000'
}
print("tx = ")
print(tx)
signedTx = web3.eth.account.sign_transaction(tx, walletKey)
txHash = web3.eth.send_raw_transaction(signedTx.raw_transaction)
print('kaiaSwap transaction')
print(web3.to_hex(txHash))
result = web3.eth.wait_for_transaction_receipt(txHash)
status = result['status']
if status == 1:
print('Transaction Succeeded')
else:
print('Transaction Failed')
data部分を変更していくだけです。