【仮想通貨botter Advent Calendar 2022】 ABIを使わずにPancakeswapでSwapしよう
本記事は仮想通貨botter Advent Calendar 2022に掲載させていただく記事です。
はじめに
はじめまして。qash_titと申します。普段はBOTを用いたアービトラージを主体として、クラウド代とメンタルを溶かしながら戦っております。
今年度は、仮想通貨botter Advent Calendar 2022に参加させていただきました。
昨年度の仮想通貨botter Advent Calendar 2021では、良質な記事(ポエム)や気づきなどがあり、参加しなかったことを後で後悔しました。
私も最近はNoteや弊ブログでポエムを書いているので、良かったら読んでみてください。
過度に利益志向にならないように、とのことなので、絆チェーンのブリッジを止めたりとか、ハニーポットを投げつけたりとか、そういうテクニック系の話はせず、「へーそうなんだ」となるくらいのことを書こうと思います。(長くて濃い話は年末にNote出します。)
「welcome to the underground」な話はオフ会とかで会ったら聞いてください。話せるところは話します。
さて、今回の題材は「ABIを使わずにPancakeswapでSwapしよう」です。
なんでこれを取り上げるかと言うと、考え方を応用すると色々なコントラクトを操作することが可能になるからです。
では、順を追って説明していきます。
i)PancakeswapのWebサイトを使う。
これは説明不要だと思います。
ii)BscscanのWriteContract(直コン)を使う。
例えば、swapExactTokensForTokensはトークンAをトークンBに交換する関数です。
PancakeswapなどのDEXでは、UIから操作するため、適切な関数を自動で選んでくれます。
そのため、普段はBNB->BUSDをSwapする時はswapExactETHForTokensを使って、とか、BUSD->USDTをする時はswapExactTokensForTokensを使って・・・、と意識することはありません。
一方、所謂直コンを使う場合は、適切な関数を選ぶ必要があります。Uniswapフォーク(Pancakeswap)のコントラクトの場合、以下の関数を使用することができます。
適宜、ETHをBNBと読み替えたり、そのチェーンの基軸通貨に読み替える必要があります。PancakeswapはUniswapをそのままフォークしているのでswapExactBNBForTokensではなくswapExactETHForTokensのようです。
今回のNoteではswapExactTokensForTokensに焦点を当てたいので、Inputについて少し細かく見ます。
例: 1USDTを0.99BUSD以上にSwapしたい。
なお、事前にトークンApproveは済ませているものとします。
(*PancakeswapのRouter addressをUSDTの1.approveで必要量をApproveする)
swapExactTokensForTokensの中身
・amountIn (uint256):1000000000000000000
(使うUSDTの量
USDTのDecimalsは18なので、1*10^18をすると1USDT扱い。)
・amountOutMin (uint256):990000000000000000
(Swapした際に最低限得たいBUSDの量
BUSDのDecimalsは18なので、0.99*10^18をすると0.99BUSD扱い)
・path (address[]):0x55d398326f99059fF775485246999027B3197955,0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56
(USDT、BUSDのコントラクトアドレスを入力)
・to (address):自分のアドレス(Swapしたトークンの行先)
・deadline (uint256):Unixtimeでの制限時間
Unixtimeと通常の日時を変換する場合はこのサイトが便利
2022-12-18 00:00:00までにSwapを行う場合1671289200となる。
上記を入力すれば所謂直コンでのSwapはできます。USDT->BUSDではなく、USDT->BUSD->CAKEをしたいならPathに入力するものを変えればOKです。簡単ですね。
iii)web3.pyなどからABIを用いてSwapする。
(コード:https://colab.research.google.com/drive/16KtsMGo30FBWBAYGEEAmQ0YWsWcQX9Ti?usp=sharing)
#Python
import time
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('https://bsc-dataseed.binance.org/'))
contract_address = Web3.toChecksumAddress('0x10ED43C718714eb63d5aA57B78B54704E256024E')#pancakeのRouter Address
account_address="自分のアドレス"#自分のアドレスに変更すること
secret_key="秘密鍵"#ホントはベタ打ちはよくない。
abi_pancake=[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
#https://bscscan.com/address/0x10ed43c718714eb63d5aa57b78b54704e256024e#code のContract ABIをコピペ
swap_contract = web3.eth.contract(contract_address, abi=abi_pancake)
amountIn = int(1*10**18)#使うUSDTの量
amountOutMin = int(0.99*10**18)#Swapした際に最低限得たいBUSDの量
input_token_address="0x55d398326f99059fF775485246999027B3197955"#USDT
output_token_address="0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"#BUSD
path = [input_token_address, output_token_address]
to="自分のアドレス"#自分のアドレスに変更すること
deadline = int(time.time() + 60)#Unixtimeでの制限時間
#swapExactTokensForTokensの中身をinput_swapにいれる
input_swap = swap_contract.functions.swapExactTokensForTokens(
amountIn,
amountOutMin,
path,
to,
deadline
)
'''
buildTransactionで
'value','gas','chainId','from','nonce','gasPrice','to','data':の値を作る
'''
tx = input_swap.buildTransaction({
'from': account_address,
'nonce': web3.eth.getTransactionCount(account_address),
'gasPrice': Web3.toWei('5', 'gwei'),
})
print(tx['data'])
signed_tx = web3.eth.account.signTransaction(tx, secret_key)
#emitted = web3.eth.sendRawTransaction(signed_tx.rawTransaction) #実際にTXを送る時はコメントアウトすること。
流れとしてはii)のようにswapExactTokensForTokensで必要なInputをinput_swapの中に入れ、buildTransactionでTXの中身を作り、signTransactionで秘密鍵で署名、sendRawTransactionでTxを送る、となって います。
細かい変数の意味はコメントに書いておいたのでそっちを読んでください。
web3.pyでSwapする場合、ほとんどの人はこのやり方を採用しているのではないでしょうか。
ただ、これは下記の理由でTXを送る速度は遅いです。
なので、私はこの方法でTXを送っていません。
iv)web3.pyでABIを用いずにSwapする。
やっと今日の本題です。
ABIを用いず、かつ通信回数をできる限り減らしてSwapする方法について述べます。
やることとしては、
これだけです。
a)Inputdataを生成する。
Inputdataというのは、コントラクトに含まれる関数を実行する際に必要な関数名と中身を渡すためのものです。BSCScanでは以下のような感じの数字の羅列を見たことがある人もいるかもしれません。
構成としてはMethodID(関数名みたいなもの)+64文字ずつに区分した引数となっています。
swapExactTokensForTokensの場合、コントラクト内では
swapExactTokensForTokens
(uint256 amountIn, uint256 amountOutMin, address[] path
, address to, uint256 deadline)
と定義されており、これを日本語に直すと、
swapExactTokensForTokensという関数は、
uint256型のamountIn
uint256型のamountOutMin
address[]型のpath
address型のto
uint256型のdeadline
で構成されることを意味します。
これをInputDataに変換する場合、swapExactTokensForTokensをMethodIDに変換(0x38ed1739)し、amountInなどの必要な事項を書けばOKです。0x38ed1739はルーターアドレスを見て、他の人がSwapしている内容を10文字分パクればOKです。
(*ちゃんとやりたい場合は、以下のようなコードを動かせばMethodIDは取得できます。)
#web3.pyのインストール Resetruntimeを押すこと
!pip install web3
!pip uninstall -y sha3
!pip uninstall -y pysha3
!pip install pysha3
from Crypto.Hash import keccak
import binascii
keccak256 = keccak.new(data=b"swapExactTokensForTokens(uint256,uint256,address[],address,uint256)", digest_bits=256).digest()
'0x'+str(binascii.hexlify(keccak256))[2:10]
swapExactTokensForTokensの場合、具体的にどのようなInputDataを作れば良いかと言うと、
#作る必要があるInputDataの中身
0x38ed1739#MethodID
0000000000000000000000000000000000000000000000008ac7230489e80000#amountIn
0000000000000000000000000000000000000000000000008963dd8c2c5e0000#amountOutMin
00000000000000000000000000000000000000000000000000000000000000a0#謎
0000000000000000000000000000000000000000000000000000000000000000#to
0000000000000000000000000000000000000000000000000000000066fe9a32#deadline
0000000000000000000000000000000000000000000000000000000000000002#Pathの数
00000000000000000000000055d398326f99059fF775485246999027B3197955#USDT
000000000000000000000000e9e7CEA3DedcA5984780Bafc599bD69ADd087D56#BUSD
って感じです。
これを自動化したのがinput_generator(amountIn,amountOutMin,path)という関数で、これはRPCとの通信を必要としませんし、buildTransactionも不要です。さらに、MethodIDさえわかればABIも不要です。
input_generatorは以下です。
def input_generator(amountIn,amountOutMin,account_address,path):
mes1='0x38ed1739'
m=''
ll=int(amountIn*10**18)
for n in range(64-len(hex(ll)[2:])):
m=m+'0'
amountIn_mes=m+hex(ll)[2:]
m2=''
ll2=int(amountOutMin*10**18)
for s in range(64-len(hex(ll2)[2:])):
m2=m2+'0'
amountOutMin_mes=m2+hex(ll2)[2:]
mes2=amountIn_mes
mes3=amountOutMin_mes
mes4='00000000000000000000000000000000000000000000000000000000000000a0'
mes5='000000000000000000000000'+account_address[2:]
dt1 = datetime.datetime.now()
dt2 = dt1 + datetime.timedelta(weeks=100)
next_time=hex(int(dt2.timestamp()))[2:]
time_mes='00000000000000000000000000000000000000000000000000000000'+next_time
mes6=time_mes
mes7='0000000000000000000000000000000000000000000000000000000000000002'#path数
mes8='000000000000000000000000'+path[0][2:]#USDT
mes9='000000000000000000000000'+path[1][2:]#BUSD
all_mes=mes1+mes2+mes3+mes4+mes5+mes6+mes7+mes8+mes9
return all_mes
上記の関数を読み込んだ上で以下の関数を実行すると、iii)で取り上げたbuildTransactionとほぼ同じものができます。
b)生成したInputdataを用いてRouter addressにTXを送信する。
#Python
import time
from web3 import Web3
import datetime
web3 = Web3(Web3.HTTPProvider('https://bsc-dataseed.binance.org/'))
account_address="0x2f9c38bD6E2F382C031bfda65aeA2b76BEcD6808"#自分のアドレスに変更すること このアドレスは適当
secret_key="秘密鍵"#ホントはベタ打ちはよくない。
nonce=web3.eth.getTransactionCount(account_address)
amountIn=int(1*10**18)#USDTのSwap量
amountOutMin=int(0.99*10**18)#BUSDのSwap量
input_token_address="0x55d398326f99059fF775485246999027B3197955"#USDT
output_token_address="0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"#BUSD
path = [input_token_address, output_token_address]
all_mes=input_generator(amountIn,amountOutMin,account_address,path)
tx={'chainId': 56,#BSCのChainID
'nonce': nonce,#nonceはweb3.eth.getTransactionCount(account_address)で取得
'to': '0x10ED43C718714eb63d5aA57B78B54704E256024E',#pancakeのRouterアドレス
'value': web3.toWei(0, 'gwei'),#送金するBNBの量
'gas': 30000000,#Gaslimit
'gasPrice': web3.toWei(5, 'gwei'),#Gas代
'data':all_mes}#インプット
#signed_tx = web3.eth.account.signTransaction(tx, secret_key)
#emitted = web3.eth.sendRawTransaction(signed_tx.rawTransaction) #実際にTXを送る時はコメントアウトすること。
tx
これはiii)とほぼ同じで、signTransaction、sendRawTransactionを使えばOKです。
(動かしたい人は以下からどうぞ)
https://colab.research.google.com/drive/1h0fz_Y5bm8bzqa2SXmg3Y84zNbfmcrol?usp=sharing
まとめと応用
今回は簡単のためにswapExactTokensForTokensを取り上げましたが、MethodIDと中身さえわかれば、ABI不要でどんなコントラクトでも実行することが可能です。(*onlyOwnerなどのホワリスが設定されていない場合のみ)
具体的な応用は以下です。
①Uniswap型のDEXであることはわかっているけど、コントラクトがVerifyされておらず、ABIが取得できないパターン。
例えばSyscoinのpegasys.financeはコードがVerifyされていない。
また、swapExactTokensForXXXなど、独自DEXになっている場合は既存のABIを読み込む方式では対応不可ですが、今回の方式ではMethodIDさえわかれば実行可能。
②NFTの早押しMint
例えばJOJOはInputdataが割れていたので以下のようなInputでTXを送れば早押しMintには勝てた。
③他人のアビトラコントラクト
具体例を出すのは辞めておきますが、他人のアビトラコントラクトにハニポトークン(Scam)を踏ませることも可能。
もちろん、onlyOwnerなどがないコントラクトでないと不可能。
今回の内容は以上です! 以前とあるDiscordでBOT配布したのですが、buildTransactionをしないのは初めて見た、と言われたので意外と知られてないのかもな、と思って書きました。
getAmountsoutをRPCで呼び出しつつ、鞘がある時に上記のコードでswapするだけでも、魔界(Metis)の最初期は30万ドルほど取れたのでバブルが恋しいです。
コメント、指摘などはTwitterまで!