From e20bc723462056ac94622395b84dcd4a543b9224 Mon Sep 17 00:00:00 2001 From: Boyuan-Chen <46272347+Boyuan-Chen@users.noreply.github.com> Date: Wed, 20 Apr 2022 15:23:32 -0700 Subject: [PATCH] Add proxy contract for Boba_GasPriceOracle (#123) --- ...e.sol => Boba_GasPriceOracleProxyCall.sol} | 2 +- .../test/boba-fee-payment.spec.ts | 47 +++++++++++++------ .../constants/Lib_PredeployAddresses.sol | 4 ++ packages/contracts/src/make-genesis.ts | 45 ++++++++++++++---- packages/contracts/src/predeploys.ts | 3 +- 5 files changed, 76 insertions(+), 25 deletions(-) rename integration-tests/contracts/{Proxy__Boba_GasPriceOracle.sol => Boba_GasPriceOracleProxyCall.sol} (94%) diff --git a/integration-tests/contracts/Proxy__Boba_GasPriceOracle.sol b/integration-tests/contracts/Boba_GasPriceOracleProxyCall.sol similarity index 94% rename from integration-tests/contracts/Proxy__Boba_GasPriceOracle.sol rename to integration-tests/contracts/Boba_GasPriceOracleProxyCall.sol index b2df626097..a0f76c1eaf 100644 --- a/integration-tests/contracts/Proxy__Boba_GasPriceOracle.sol +++ b/integration-tests/contracts/Boba_GasPriceOracleProxyCall.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.9; -contract Proxy__Boba_GasPriceOracle { +contract Boba_GasPriceOracleProxyCall { address public gasPriceOracleAddress; constructor(address _gasPriceOracleAddress) { diff --git a/integration-tests/test/boba-fee-payment.spec.ts b/integration-tests/test/boba-fee-payment.spec.ts index b1f13e320a..a320bdd6a4 100644 --- a/integration-tests/test/boba-fee-payment.spec.ts +++ b/integration-tests/test/boba-fee-payment.spec.ts @@ -13,7 +13,7 @@ import { OptimismEnv } from './shared/env' import { gasPriceOracleWallet } from './shared/utils' /* Imports: ABI */ -import Proxy__Boba_GasPriceOracleJson from '../artifacts/contracts/Proxy__Boba_GasPriceOracle.sol/Proxy__Boba_GasPriceOracle.json' +import Boba_GasPriceOracleProxyCallJson from '../artifacts/contracts/Boba_GasPriceOracleProxyCall.sol/Boba_GasPriceOracleProxyCall.json' const setPrices = async (env: OptimismEnv, value: number | BigNumber) => { const gasPrice = await env.messenger.contracts.l2.OVM_GasPriceOracle.connect( @@ -31,10 +31,11 @@ describe('Boba Fee Payment Integration Tests', async () => { let L1Boba: Contract let L2Boba: Contract let Boba_GasPriceOracle: Contract - - let Factory__Proxy__Boba_GasPriceOracle: ContractFactory let Proxy__Boba_GasPriceOracle: Contract + let Factory__Boba_GasPriceOracleProxyCall: ContractFactory + let Boba_GasPriceOracleProxyCall: Contract + const other = '0x1234123412341234123412341234123412341234' before(async () => { @@ -47,20 +48,35 @@ describe('Boba Fee Payment Integration Tests', async () => { .attach(predeploys.L2GovernanceERC20) .connect(env.l2Wallet) Boba_GasPriceOracle = getContractFactory('Boba_GasPriceOracle') - .attach(predeploys.Boba_GasPriceOracle) + .attach(predeploys.Proxy__Boba_GasPriceOracle) + .connect(env.l2Wallet) + + Proxy__Boba_GasPriceOracle = getContractFactory( + 'Lib_ResolvedDelegateBobaProxy' + ) + .attach(predeploys.Proxy__Boba_GasPriceOracle) .connect(env.l2Wallet) - Factory__Proxy__Boba_GasPriceOracle = new ethers.ContractFactory( - Proxy__Boba_GasPriceOracleJson.abi, - Proxy__Boba_GasPriceOracleJson.bytecode, + Factory__Boba_GasPriceOracleProxyCall = new ethers.ContractFactory( + Boba_GasPriceOracleProxyCallJson.abi, + Boba_GasPriceOracleProxyCallJson.bytecode, env.l2Wallet ) - Proxy__Boba_GasPriceOracle = - await Factory__Proxy__Boba_GasPriceOracle.deploy( + Boba_GasPriceOracleProxyCall = + await Factory__Boba_GasPriceOracleProxyCall.deploy( Boba_GasPriceOracle.address ) - await Proxy__Boba_GasPriceOracle.deployTransaction.wait() + await Boba_GasPriceOracleProxyCall.deployTransaction.wait() + }) + + it('{tag:boba} should have correct proxy target and proxy owner', async () => { + expect( + await Proxy__Boba_GasPriceOracle.addressManager('proxyOwner') + ).to.be.eq(env.l1Wallet.address) + expect( + await Proxy__Boba_GasPriceOracle.addressManager('proxyTarget') + ).to.be.eq(predeploys.Boba_GasPriceOracle) }) it('{tag:boba} should register to use boba as the fee token', async () => { @@ -74,8 +90,9 @@ describe('Boba Fee Payment Integration Tests', async () => { }) it('{tag:boba} should not register the fee tokens for non EOA accounts', async () => { - await expect(Proxy__Boba_GasPriceOracle.useBobaAsFeeToken()).to.be.reverted - await expect(Proxy__Boba_GasPriceOracle.useETHAsFeeToken()).to.be.reverted + await expect(Boba_GasPriceOracleProxyCall.useBobaAsFeeToken()).to.be + .reverted + await expect(Boba_GasPriceOracleProxyCall.useETHAsFeeToken()).to.be.reverted }) it('{tag:boba} Paying a nonzero but acceptable boba gasPrice fee for transferring ETH', async () => { @@ -636,7 +653,7 @@ describe('Boba Fee Payment Integration Tests', async () => { Boba_GasPriceOracle.address ) - const TestContract = await Factory__Proxy__Boba_GasPriceOracle.deploy( + const TestContract = await Factory__Boba_GasPriceOracleProxyCall.deploy( Boba_GasPriceOracle.address ) const receipt = await TestContract.deployTransaction.wait() @@ -667,7 +684,7 @@ describe('Boba Fee Payment Integration Tests', async () => { it('{tag:boba} should pay BOBA to deploy contracts for different gas limit', async () => { await setPrices(env, 1000) - const data = Factory__Proxy__Boba_GasPriceOracle.getDeployTransaction( + const data = Factory__Boba_GasPriceOracleProxyCall.getDeployTransaction( Boba_GasPriceOracle.address ) const estimatedGas = await env.l2Wallet.estimateGas(data) @@ -683,7 +700,7 @@ describe('Boba Fee Payment Integration Tests', async () => { Boba_GasPriceOracle.address ) - const TestContract = await Factory__Proxy__Boba_GasPriceOracle.deploy( + const TestContract = await Factory__Boba_GasPriceOracleProxyCall.deploy( Boba_GasPriceOracle.address ) const receipt = await TestContract.deployTransaction.wait() diff --git a/packages/contracts/contracts/libraries/constants/Lib_PredeployAddresses.sol b/packages/contracts/contracts/libraries/constants/Lib_PredeployAddresses.sol index 90fff7f3c1..0bde41999d 100644 --- a/packages/contracts/contracts/libraries/constants/Lib_PredeployAddresses.sol +++ b/packages/contracts/contracts/libraries/constants/Lib_PredeployAddresses.sol @@ -25,4 +25,8 @@ library Lib_PredeployAddresses { 0x4200000000000000000000000000000000000020; address internal constant BOBA_TURING_PREPAY = 0x4200000000000000000000000000000000000021; address internal constant BOBA_TURING_HELPER = 0x4200000000000000000000000000000000000022; + address internal constant L2_BOBA = 0x4200000000000000000000000000000000000023; + address internal constant PROXY__BOBA_GAS_PRICE_ORACLE = + 0x4200000000000000000000000000000000000024; + address internal constant BOBA_GAS_PRICE_ORACLE = 0x4200000000000000000000000000000000000025; } diff --git a/packages/contracts/src/make-genesis.ts b/packages/contracts/src/make-genesis.ts index 2695b8e48d..c9c552058c 100644 --- a/packages/contracts/src/make-genesis.ts +++ b/packages/contracts/src/make-genesis.ts @@ -52,6 +52,19 @@ export interface RollupDeployConfig { berlinBlock: number } +const addSlotsForBobaProxyContract = ( + dump: any, predeployAddress: string, variable: any +) => { + for (const keyName of Object.keys(variable)) { + const key = utils.hexlify(utils.toUtf8Bytes(keyName)); + const index = BigNumber.from('0').toHexString(); + const newKeyPreimage = utils.concat([key, utils.hexZeroPad(index, 32)]); + const compositeKey = utils.keccak256(utils.hexlify(newKeyPreimage)); + dump[predeployAddress].storage[compositeKey] = variable[keyName] + } + return dump +} + /** * Generates the initial state for the L2 system by injecting the relevant L2 system contracts. * @@ -123,6 +136,10 @@ export const makeL2GenesisFile = async ( l1Token: cfg.l1BobaTokenAddress, l2Bridge:predeploys.L2StandardBridge, }, + Proxy__Boba_GasPriceOracle: { + proxyOwner: cfg.deployer, + proxyTarget: predeploys.Boba_GasPriceOracle + }, Boba_GasPriceOracle: { _owner: cfg.gasPriceOracleOwner, feeWallet: cfg.l1FeeWalletAddress, @@ -152,11 +169,17 @@ export const makeL2GenesisFile = async ( // and returns the address given by that opcode. dump[predeployAddress].code = '0x4B60005260206000F3' } else if (predeployName === 'BobaTuringHelper') { + // Add a default BobaTuringHelper for testing purposes dump[predeployAddress].code = cfg.TuringHelperJson.deployedBytecode - } else if (predeployName === 'L2GovernanceERC20') { + // Fix the address(this) of L2GovernanceERC20 dump[predeployAddress].code = L2GovernanceERC20Helper.L2GovernanceERC20Bytecode + } else if (predeployName === 'Proxy__Boba_GasPriceOracle') { + // Add proxy contract for Boba_GasPriceOracle + const artifact = getContractArtifact('Lib_ResolvedDelegateBobaProxy') + dump[predeployAddress].code = artifact.deployedBytecode } else { + // Standard case: get the deployed bytecode from the artifact const artifact = getContractArtifact(predeployName) dump[predeployAddress].code = artifact.deployedBytecode } @@ -164,26 +187,32 @@ export const makeL2GenesisFile = async ( // Compute and set the required storage slots for each contract that needs it. if (predeployName in variables) { if (predeployName === 'BobaTuringHelper') { + // Add a default BobaTuringHelper for testing purposes const indexOwner = BigNumber.from('0').toHexString(); dump[predeployAddress].storage[utils.hexZeroPad(indexOwner, 32)] = cfg.deployer const indexAddress = BigNumber.from('1').toHexString(); dump[predeployAddress].storage[utils.hexZeroPad(indexAddress, 32)] = predeploys.BobaTuringHelper continue } + if (predeployName === 'Proxy__Boba_GasPriceOracle') { + // Add a proxy contract for Boba_GasPriceOracle + addSlotsForBobaProxyContract(dump, predeployAddress, variables[predeployName]) + const storageLayout = await getStorageLayout('Boba_GasPriceOracle') + const slots = computeStorageSlots(storageLayout, variables['Boba_GasPriceOracle']) + for (const slot of slots) { + dump[predeploys.Proxy__Boba_GasPriceOracle].storage[slot.key] = slot.val + } + continue + } const storageLayout = await getStorageLayout(predeployName) // Calculate the mapping keys if (predeployName === 'Lib_ResolvedDelegateBobaProxy') { - for (const keyName of Object.keys(variables[predeployName])) { - const key = utils.hexlify(utils.toUtf8Bytes(keyName)); - const index = BigNumber.from('0').toHexString(); - const newKeyPreimage = utils.concat([key, utils.hexZeroPad(index, 32)]); - const compositeKey = utils.keccak256(utils.hexlify(newKeyPreimage)); - dump[predeployAddress].storage[compositeKey] = variables[predeployName][keyName] - } + addSlotsForBobaProxyContract(dump, predeployAddress, variables[predeployName]) } else { const slots = computeStorageSlots(storageLayout, variables[predeployName]) for (const slot of slots) { dump[predeployAddress].storage[slot.key] = slot.val + // Add the storage slots for Proxy__BobaTuringCredit if (predeployName === "BobaTuringCredit") { dump[predeploys.Lib_ResolvedDelegateBobaProxy].storage[slot.key] = slot.val } diff --git a/packages/contracts/src/predeploys.ts b/packages/contracts/src/predeploys.ts index 213346d545..93865185dc 100644 --- a/packages/contracts/src/predeploys.ts +++ b/packages/contracts/src/predeploys.ts @@ -33,5 +33,6 @@ export const predeploys = { L2GovernanceERC20: "0x4200000000000000000000000000000000000023", // Boba gas price oracle - Boba_GasPriceOracle: "0x4200000000000000000000000000000000000024" + Proxy__Boba_GasPriceOracle: "0x4200000000000000000000000000000000000024", + Boba_GasPriceOracle: "0x4200000000000000000000000000000000000025" }