> ## Documentation Index
> Fetch the complete documentation index at: https://docs.optimism.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Modifying predeployed contracts

> Learn how to modify predeployed contracts for an OP Stack chain by upgrading the proxy.

<Info>
  OP Stack Hacks are explicitly things that you can do with the OP Stack that are *not* currently intended for production use.

  OP Stack Hacks are not for the faint of heart. You will not be able to receive significant developer support for OP Stack Hacks. Be prepared to get your hands dirty and to work without support.
</Info>

OP Stack blockchains have a number of [predeployed contracts](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/libraries/Predeploys.sol) that provide important functionality.
Most of those contracts are proxies that can be upgraded using the `proxyAdminOwner` which was configured when the network was initially deployed.

## Before you begin

In this tutorial, you learn how to modify predeployed contracts for an OP Stack chain by upgrading the proxy. The predeploys are controlled from a predeploy called [`ProxyAdmin`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/universal/ProxyAdmin.sol), whose address is `0x4200000000000000000000000000000000000018`.
The function to call is [`upgrade(address,address)`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/universal/ProxyAdmin.sol#L152-L168).
The first parameter is the proxy to upgrade, and the second is the address of a new implementation.

## Modify the legacy `L1BlockNumber` contract

For example, the legacy `L1BlockNumber` contract is at `0x420...013`.
To disable this function, we'll set the implementation to `0x00...00`.
We do this using the [Foundry](https://book.getfoundry.sh/) command `cast`.

<Steps>
  <Step title="We'll need several constants.">
    * Set these addresses as variables in your terminal.

      ```sh theme={null}
      L1BLOCKNUM=0x4200000000000000000000000000000000000013
      PROXY_ADMIN=0x4200000000000000000000000000000000000018
      ZERO_ADDR=0x0000000000000000000000000000000000000000
      ```

    * Set `PRIVKEY` to the private key of your ADMIN address.

    * Set `ETH_RPC_URL`. If you're on the computer that runs the blockchain, use this command.

      ```sh theme={null}
      export ETH_RPC_URL=http://localhost:8545
      ```
  </Step>

  <Step title="Verify `L1BlockNumber` works correctly.">
    See that when you call the contract you get a block number, and twelve seconds later you get the next one (block time on L1 is twelve seconds).

    ```sh theme={null}
    cast call $L1BLOCKNUM 'number()' | cast --to-dec
    sleep 12 && cast call $L1BLOCKNUM 'number()' | cast --to-dec
    ```
  </Step>

  <Step title="Get the current implementation for the contract.">
    ```sh theme={null}
      L1BLOCKNUM_IMPLEMENTATION=`cast call $L1BLOCKNUM "implementation()" | sed 's/000000000000000000000000//'`
      echo $L1BLOCKNUM_IMPLEMENTATION 
    ```
  </Step>

  <Step title="Change the implementation to the zero address">
    ```sh theme={null}
      cast send --private-key $PRIVKEY $PROXY_ADMIN "upgrade(address,address)" $L1BLOCKNUM $ZERO_ADDR
    ```
  </Step>

  <Step title="See that the implementation is address zero, and that calling it fails.">
    ```sh theme={null}
      cast call $L1BLOCKNUM 'implementation()'
      cast call $L1BLOCKNUM 'number()'
    ```
  </Step>

  <Step title="Fix the predeploy by returning it to the previous implementation, and verify it works.">
    ```sh theme={null}
      cast send --private-key $PRIVKEY $PROXY_ADMIN "upgrade(address,address)" $L1BLOCKNUM $L1BLOCKNUM_IMPLEMENTATION
      cast call $L1BLOCKNUM 'number()' | cast --to-dec
    ```
  </Step>
</Steps>
