# Proxy contracts

{% hint style="info" %}
To shadow a contract that is proxied, you’ll need to make shadow changes at the underlying implementation contract address. If the implementation contract changes, you’ll need to shadow the new implementation contract.
{% endhint %}

A **proxy** contract is a smart contract that forwards transactions to another **implementation** contract containing the business logic. The proxy acts as an intermediary, allowing the implementation to be updated without changing the contract address users interact with.

```
User ---- tx ---> Proxy ----------> Implementation_v0
                     |
                      ------------> Implementation_v1
                     |
                      ------------> Implementation_v2
```

For this example, we will be shadowing USDC to emit a custom event on every transfer. The custom event will be called `TransferWithMetadata`, and will contain additional metadata about the transfer, including the before and after balances, and the percent change.

USDC follows a proxy pattern with the following addresses:

* **Proxy:** [`0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48`](https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48)
* **Implementation:** [`0x43506849d7c04f9138d1a2050bbf3a0c054402dd`](https://etherscan.io/address/0x43506849d7c04f9138d1a2050bbf3a0c054402dd) (as of Jul 2024)

## Step 1 – Edit the implementation contract

Open the example on the Shadow Playground: <https://app.shadow.xyz/demo?example=usdc_proxy>

This will open the playground editor at the implementation contract at [`0x43506849d7c04f9138d1a2050bbf3a0c054402dd`](https://etherscan.io/address/0x43506849d7c04f9138d1a2050bbf3a0c054402dd) (as of Jul 2024).

The bulk of the shadow contract changes lives in the `FiatTokenV1.sol` file.

At L57, we’ve defined the `TransferWithMetadata` event and a helper `TransferMetadata` struct:

```solidity
struct TransferMetadata {
    uint256 balanceBefore;
    uint256 balanceAfter;
    int256 percentChange;
}

event TransferWithMetadata(
    address from, 
    address to, 
    uint256 amount, 
    TransferMetadata fromMetadata, 
    TransferMetadata toMetadata
);
```

Then lower down in the same file, we updated the `_transfer` function to emit our `TransferWithMetadata` shadow event:

```solidity
function _transfer(
    address from,
    address to,
    uint256 value
) internal override {
    require(from != address(0), "ERC20: transfer from the zero address");
    require(to != address(0), "ERC20: transfer to the zero address");
    require(
        value <= _balanceOf(from),
        "ERC20: transfer amount exceeds balance"
    );

    uint256 fromBalanceBefore = _balanceOf(from);
    uint256 fromBalanceAfter = _balanceOf(from).sub(value);
    int256 fromPercentChange = -int256(value * uint256(10)**uint256(6) / fromBalanceBefore);
    TransferMetadata memory fromTransferMetadata = TransferMetadata({
        balanceBefore: fromBalanceBefore,
        balanceAfter: fromBalanceAfter,
        percentChange: fromPercentChange
    });

    uint256 toBalanceBefore = _balanceOf(to);
    uint256 toBalanceAfter = _balanceOf(to).add(value);
    int256 toPercentChange = int256(value * uint256(10)**uint256(6) / toBalanceBefore);
    TransferMetadata memory toTransferMetadata = TransferMetadata({
        balanceBefore: toBalanceBefore,
        balanceAfter: toBalanceAfter,
        percentChange: toPercentChange
    });

    emit TransferWithMetadata(from, to, value, fromTransferMetadata, toTransferMetadata);

    _setBalance(from, _balanceOf(from).sub(value));
    _setBalance(to, _balanceOf(to).add(value));
    emit Transfer(from, to, value);
}
```

## Step 2 – Test run your changes

Click “Compile” > “Test Run” in the top right corner, and paste in this transaction hash [`0x8364a18d685976fd640a5ef24d9c8ef8a4eb25141d125ec87b642241dbedf853`](https://etherscan.io/tx/0x8364a18d685976fd640a5ef24d9c8ef8a4eb25141d125ec87b642241dbedf853)–– or you can simulate any other transaction that transferred USDC.

You should see your custom `TransferWithMetadata` in the output!

<figure><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdQqG3S9gnk6QLNWta_LI0gb6OqI-IdwCJg6hIpzVJP5n2du0XCkwAAhIABoexJ7jhPuDDjy6Nwqj9rsYwk5TZKOJL5Y4frexyujspihYm3Y--blexEUeHGujwMZ64prVnQmCBrC5DVSBwFlbJIdfzxIeY?key=qOOFy18EQhEZbpSRGduGxQ" alt=""><figcaption></figcaption></figure>

## **Step 3 – Deploy your changes**

If you want to apply these changes on your shadow fork, click the button on the top right corner that says “Apply to your shadow fork”.

This will take you to the editor for your shadow fork, where you can deploy the changes by hitting “Compile > Deploy”.

## **Step 4 – Getting your data**

Events added to an implementation contract are emitted by the **proxy contract**.

So if you want to see a realtime feed of your shadow events, you'll need to navigate to the **proxy contract address** [`0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48`](https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48).

<figure><img src="/files/8gTVOoR5KdbhhrIzfcwT" alt=""><figcaption></figcaption></figure>

This means that if you are retrieving data via RPC, you'll need to filter by the **proxy contract address**.

Similarly, if you are setting up a data export, you'll need to select the **proxy contract address.**


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.shadow.xyz/modify-contracts/how-tos/proxy-contracts.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
