Modifying Predeployed Contracts
🚧 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.
OP Stack blockchains have a number of predeployed contracts (opens new window) 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.
The predeploys are controlled from a predeploy called
ProxyAdmin (opens new window), whose address is
The function to call is
upgrade(address,address) (opens new window).
The first parameter is the proxy to upgrade, and the second is the address of a new implementation.
For example, the legacy
L1BlockNumber contract is at
To disable this function, we'll set the implementation to
We do this using the Foundry (opens new window) command
We'll need several constants.
Set these addresses as variables in your terminal.
L1BLOCKNUM=0x4200000000000000000000000000000000000013 PROXY_ADMIN=0x4200000000000000000000000000000000000018 ZERO_ADDR=0x00000000000000000000000000000000000000001
PRIVKEYto the private key of your ADMIN account.
ETH_RPC_URL. If you're on the computer that runs the blockchain, use this command.
L1BlockNumberworks 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).
cast call $L1BLOCKNUM 'number()' | cast --to-dec sleep 12 && cast call $L1BLOCKNUM 'number()' | cast --to-dec1
Get the current implementation for the contract.
L1BLOCKNUM_IMPLEMENTATION=`cast call $L1BLOCKNUM "implementation()" | sed 's/000000000000000000000000//'` echo $L1BLOCKNUM_IMPLEMENTATION1
Change the implementation to the zero address
cast send --private-key $PRIVKEY $PROXY_ADMIN "upgrade(address,address)" $L1BLOCKNUM $ZERO_ADDR1
See that the implementation is address zero, and that calling it fails.
cast call $L1BLOCKNUM 'implementation()' cast call $L1BLOCKNUM 'number()'1
Fix the predeploy by returning it to the previous implementation, and verify it works.
cast send --private-key $PRIVKEY $PROXY_ADMIN "upgrade(address,address)" $L1BLOCKNUM $L1BLOCKNUM_IMPLEMENTATION cast call $L1BLOCKNUM 'number()' | cast --to-dec1