Developer guide

    How to Call Functions on a Proxy Contract

    Upgradeable contracts store their logic somewhere else. The explorer shows a near-empty proxy with three functions, while the ones you actually want live in the implementation. Here is how to bridge the two.

    Proxy vs Implementation

    A proxy holds all the state (balances, owners, mappings) and forwards every unknown call to an implementation contract via delegatecall. The implementation holds the code but none of the data. Upgrading means pointing the proxy at a new implementation address — the state stays put.

    you -> proxy address        (state lives here, this is the address you call)
            └─ delegatecall ─> implementation  (code lives here, ABI comes from here)

    The rule that follows: use the implementation's ABI at the proxy's address. Calling the implementation directly reads empty state and, for writes, usually reverts or corrupts an unused contract.

    Finding the Implementation Address

    EIP-1967 storage slot (most common)

    Transparent and UUPS proxies store the implementation at a fixed slot. Read it with eth_getStorageAt:

    slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
         (= keccak256("eip1967.proxy.implementation") - 1)

    The last 20 bytes of the returned word are the implementation address. The admin lives at …eip1967.proxy.admin, and beacon proxies at …eip1967.proxy.beacon.

    A public getter

    Many proxies expose implementation(), getImplementation() or childImplementation(). Add just that one function to a minimal ABI and read it from the proxy.

    The explorer's own hint

    Verified proxies often show "Read as Proxy" plus a link to the implementation. Grab the implementation's verified ABI from there — then come back and use it against the proxy address.

    Minimal proxies (EIP-1167 clones)

    The target address is baked into the 45-byte bytecode. Read the contract's code and the implementation is the 20-byte run in the middle, between 363d3d373d3d3d363d73 and 5af43d82803e903d91602b57fd5bf3.

    Putting It Together

    1. Resolve the implementation address using one of the methods above.
    2. Copy the implementation's ABI (verified source, your build artifacts, or a standard interface).
    3. In ABI Page Builder, paste that ABI but enter the proxy address as the contract address.
    4. Verify with a read: name(), totalSupply() or owner() should return real values, not zeros.
    5. Share the generated link — anyone hitting it gets the same correct proxy-plus-ABI pairing.

    Pitfalls

    • All-zero reads usually mean you pointed the ABI at the implementation instead of the proxy.
    • After an upgrade the ABI can change. If a function that used to work now reverts, re-read the implementation slot.
    • Transparent proxies deliberately block the admin account from calling implementation functions — use a non-admin wallet.
    • initialize() on the proxy is a one-time call. Calling it again reverts with "Initializable: contract is already initialized".
    • Beacon proxies add a hop: proxy -> beacon -> implementation. Read the beacon, then its implementation().

    👉 Got the implementation ABI?

    Build a contract page

    Related Guides