Search code examples
pythonethereumsmartcontractsweb3py

How do I find the correct ABI, containing the function to transfer tokens to Polygon zkEVM bridge contract?


I am writing python code to transfer tokens from ETH wallet to smart contract of Polygon zkEVM Native Bridge (https://wallet.polygon.technology) with address 0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe (https://etherscan.io/address/0x2a3dd3eb832af982ec71669e178424b10dca2ede). If you follow the link you can also find contract ABI (and other data):

[{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"admin_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

Now here is my code:

from web3 import Web3
import logging

polygon_zkEVM_RPC = "https://zkevm-rpc.com"
polygon_zkEVM_contract = "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe"
polygon_zkEVM_bridge_abi = [{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"anonymous":False,"inputs":[{"indexed":False,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":False,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":False,"inputs":[{"indexed":True,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":False,"inputs":[{"indexed":True,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"admin_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

mnemonic = config.mnemonic 

def bridge_polygon_zkEVM(name, owner_id, mnemonic):
    logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S",
                        filename=f"wallet_{name}_{owner_id}.log")
    web3 = Web3(Web3.HTTPProvider(polygon_zkEVM_RPC))
    web3.eth.account.enable_unaudited_hdwallet_features()
    account = web3.eth.account.from_mnemonic(mnemonic)
    private_key = account._private_key
    address = account.address
    logging.info(f"connected to wallet {name} | address {address} | network {polygon_zkEVM_RPC} | owner_id "
                 f"{owner_id}")
    contract = web3.eth.contract(address=web3.to_checksum_address(polygon_zkEVM_contract), abi=polygon_zkEVM_bridge_abi)
    gas_price_gwei = 10
    transaction = {
        'to': polygon_zkEVM_contract,
        'gas': web3.eth.estimate_gas(
            {'to': polygon_zkEVM_contract, 'data': contract.functions.bridgeAsset().buildTransaction()}),
        'gasPrice': web3.to_wei(gas_price_gwei, 'gwei'),
        'nonce': web3.eth.get_transaction_count(address),
        'from': address
    }
    signed_txn = web3.eth.account.sign_transaction(transaction, private_key)
    transaction_hash = web3.eth.send_raw_transaction(signed_txn.rawTransaction)
    transaction_receipt = web3.eth.wait_for_transaction_receipt(transaction_hash)

bridge_polygon_zkEVM('main', 1234, mnemonic)

If I launch it, the following error arises:

Traceback (most recent call last):
  File "C:\Users\childoflogos\Desktop\airdrop_hunter\api.py", line 58, in <module>
    bridge_polygon_zkEVM('main', 1234, mnemonic)
  File "C:\Users\childoflogos\Desktop\airdrop_hunter\api.py", line 25, in bridge_polygon_zkEVM
    {'to': polygon_zkEVM_contract, 'data': contract.functions.bridgeAsset().buildTransaction()}),
                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\childoflogos\Desktop\airdrop_hunter\venv\Lib\site-packages\web3\contract\contract.py", line 397, in __getattr__
    raise ABIFunctionNotFound(
web3.exceptions.ABIFunctionNotFound: ("The function 'bridgeAsset' was not found in this contract's abi.", ' Are you sure you provided the correct contract abi?')

And it is right, there is no such function in contract ABI if you look through it. So I decided to make a transaction (transfer of tokens to Polygon zkEVM network through the bridge) manually and find out real contract id, ABI and function name.

Here is input data of transaction on etherscan (view transaction at https://etherscan.io/tx/0x1c0c723c1408354a1123a138693af2f70ff20f3aeb136e75bc7b6fb0e46f213d):

Function: bridgeAsset(uint32 destinationNetwork,address destinationAddress,uint256 amount,address token,bool forceUpdateGlobalExitRoot,bytes permitData) ***

So, the function name in my code is right. My question is: where do I find the correct ABI of this contract which contains my function name or what is the right name of the function to put into my code for everything to work correctly?


Solution

  • The ABI you currently have is the ABI for the transparent proxy contract. To get the ABI for the actual functions you can get the ABI of the implementation contract. You can find it here: Implementation Contract