The script uses quoteExactOutput to calculate the amount of token that will be received and then immediately performs the swap.
Each time quoteExactOutput shows the amount slightly higher than what is actually obtained in the swap. This difference can be 0.1%, or it can reach 2%. This inaccuracy occurs in pools of different percentages (0.01, 0.05, 0.3, 1).
For example:
First exchange of coin for ether in the 0.05 pool:
quoteExactOutput -> 0.00004094
actually got -> 0.00004090
difference: 0.1%
Second exchange immediately after the first:
quoteExactOutput -> 0.00004094
actually got -> 0.00004090
difference: 0.1%
from web3 import Account, Web3
from abi import UNISWAP_V3_QUOTER2_ABI, UNISWAP_V3_ROUTER2_ABI, WETH9_ABI, MIN_ERC20_ABI
import eth_abi.packed
private_key = "pppppppppppppppppppppppppppppppppppppppppppppppppppp"
rpc_endpoint = "https://arb1.arbitrum.io/rpc"
web3 = Web3(Web3.HTTPProvider(rpc_endpoint))
account = Account.from_key(private_key)
weth_address = web3.to_checksum_address("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
link_address = web3.to_checksum_address("0xf97f4df75117a78c1a5a0dbb814af92458539fb4")
swap_router02_address = web3.to_checksum_address("0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45")
# load contracts
swap_router_contract = web3.eth.contract(address=swap_router02_address, abi=UNISWAP_V3_ROUTER2_ABI)
weth_contract = web3.eth.contract(address=weth_address, abi=WETH9_ABI)
link_contract = web3.eth.contract(address=link_address, abi=MIN_ERC20_ABI)
# finding out how many WETH I can get
UNISWAP_v3_QUOTER2_ADDRESS = "0x61fFE014bA17989E743c5F6cB21bF9697530B21e"
quoter2_contract = web3.eth.contract(address=UNISWAP_v3_QUOTER2_ADDRESS, abi=UNISWAP_V3_QUOTER2_ABI)
amount_in = 1_0000_0000_0000_0000 # 1 == 1_00_0000_0000_0000_0000 Link
path = eth_abi.packed.encode_packed(['address', 'uint24', 'address'], [link_address,500,weth_address])
amount_out, sqrtPriceX96After, initializedTicksCrossed, gasEstimate = quoter2_contract.functions.quoteExactOutput(path, amount_in).call()
print(f"for {amount_in / 10 ** 18} T1 you would get {amount_out / 10 ** 18} WETH")
# swap
path = eth_abi.packed.encode_packed(['address','uint24','address'], [link_address,500,weth_address])
tx_params = (
path,
account.address,
amount_in, # amount in
0 #min amount out
)
swap_buy_tx = swap_router_contract.functions.exactInput(tx_params).build_transaction(
{
'from': account.address,
'gas': 1500000,
'maxPriorityFeePerGas': web3.eth.max_priority_fee,
'maxFeePerGas': 80000000,
'nonce': web3.eth.get_transaction_count(account.address),
})
raw_transaction = web3.eth.account.sign_transaction(swap_buy_tx, account.key).rawTransaction
print(f"raw transaction: {raw_transaction}")
tx_hash = web3.eth.send_raw_transaction(raw_transaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f"tx hash: {Web3.to_hex(tx_hash)}")
Is it a quoteExactOutput bug?