Commit 3799b760 authored by Maurelian's avatar Maurelian Committed by Kelvin Fichter

feat(contracts): Add a new 'Burn Admin' entity to control CTC's gas burn params"

parent 2c91ca00
...@@ -34,6 +34,8 @@ services: ...@@ -34,6 +34,8 @@ services:
# these keys are hardhat's first 2 accounts, DO NOT use in production # these keys are hardhat's first 2 accounts, DO NOT use in production
DEPLOYER_PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" DEPLOYER_PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
# this address is hardhat's third accounts, DO NOT use in production
BURN_ADMIN_ADDRESS: "0xD1D84F0e28D6fedF03c73151f98dF95139700aa7"
# skip compilation when run in docker-compose, since the contracts # skip compilation when run in docker-compose, since the contracts
# were already compiled in the builder step # were already compiled in the builder step
NO_COMPILE: 1 NO_COMPILE: 1
......
...@@ -34,6 +34,8 @@ services: ...@@ -34,6 +34,8 @@ services:
# these keys are hardhat's first 2 accounts, DO NOT use in production # these keys are hardhat's first 2 accounts, DO NOT use in production
DEPLOYER_PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" DEPLOYER_PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
# this address is hardhat's third accounts, DO NOT use in production.
BURN_ADMIN_ADDRESS: "0xD1D84F0e28D6fedF03c73151f98dF95139700aa7"
GAS_PRICE_ORACLE_OWNER: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" GAS_PRICE_ORACLE_OWNER: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
# setting the whitelist owner to address(0) disables the whitelist # setting the whitelist owner to address(0) disables the whitelist
WHITELIST_OWNER: "0x0000000000000000000000000000000000000000" WHITELIST_OWNER: "0x0000000000000000000000000000000000000000"
......
import { Wallet } from 'ethers' import { Wallet, utils } from 'ethers'
import path from 'path' import path from 'path'
import dirtree from 'directory-tree' import dirtree from 'directory-tree'
import fs from 'fs' import fs from 'fs'
...@@ -17,6 +17,7 @@ import hre from 'hardhat' ...@@ -17,6 +17,7 @@ import hre from 'hardhat'
const sequencer = new Wallet(process.env.SEQUENCER_PRIVATE_KEY) const sequencer = new Wallet(process.env.SEQUENCER_PRIVATE_KEY)
const deployer = new Wallet(process.env.DEPLOYER_PRIVATE_KEY) const deployer = new Wallet(process.env.DEPLOYER_PRIVATE_KEY)
const burnAdminAddress = utils.getAddress(process.env.BURN_ADMIN_ADDRESS)
const parseEnv = () => { const parseEnv = () => {
const ensure = (env, type) => { const ensure = (env, type) => {
...@@ -54,6 +55,7 @@ const main = async () => { ...@@ -54,6 +55,7 @@ const main = async () => {
sccSequencerPublishWindow: config.sccFraudProofWindow, sccSequencerPublishWindow: config.sccFraudProofWindow,
ovmSequencerAddress: sequencer.address, ovmSequencerAddress: sequencer.address,
ovmProposerAddress: sequencer.address, ovmProposerAddress: sequencer.address,
ovmBurnAdmin: burnAdminAddress,
ovmAddressManagerOwner: deployer.address, ovmAddressManagerOwner: deployer.address,
noCompile: process.env.NO_COMPILE ? true : false, noCompile: process.env.NO_COMPILE ? true : false,
}) })
......
...@@ -87,13 +87,13 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes ...@@ -87,13 +87,13 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
**********************/ **********************/
/** /**
* Modifier to enforce that, if configured, only the OVM_Sequencer contract may * Modifier to enforce that only the OVM_BurnAdmin contract may
* successfully call a method. * successfully call a method.
*/ */
modifier onlySequencer() { modifier onlyBurnAdmin() {
require( require(
msg.sender == resolve("OVM_Sequencer"), msg.sender == resolve("OVM_BurnAdmin"),
"Only callable by the Sequencer." "Only callable by the Burn Admin."
); );
_; _;
} }
...@@ -108,7 +108,7 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes ...@@ -108,7 +108,7 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
*/ */
function setEnqueueGasCost(uint256 _enqueueGasCost) function setEnqueueGasCost(uint256 _enqueueGasCost)
external external
onlySequencer onlyBurnAdmin
{ {
enqueueGasCost = _enqueueGasCost; enqueueGasCost = _enqueueGasCost;
enqueueL2GasPrepaid = l2GasDiscountDivisor * _enqueueGasCost; enqueueL2GasPrepaid = l2GasDiscountDivisor * _enqueueGasCost;
...@@ -127,7 +127,7 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes ...@@ -127,7 +127,7 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
*/ */
function setGasDivisor(uint256 _l2GasDiscountDivisor) function setGasDivisor(uint256 _l2GasDiscountDivisor)
external external
onlySequencer onlyBurnAdmin
{ {
l2GasDiscountDivisor = _l2GasDiscountDivisor; l2GasDiscountDivisor = _l2GasDiscountDivisor;
enqueueL2GasPrepaid = _l2GasDiscountDivisor * enqueueGasCost; enqueueL2GasPrepaid = _l2GasDiscountDivisor * enqueueGasCost;
......
...@@ -39,6 +39,12 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -39,6 +39,12 @@ const deployFn: DeployFunction = async (hre) => {
name: 'OVM_Proposer', name: 'OVM_Proposer',
address: (hre as any).deployConfig.ovmProposerAddress, address: (hre as any).deployConfig.ovmProposerAddress,
}) })
await registerAddress({
hre,
name: 'OVM_BurnAdmin',
address: (hre as any).deployConfig.ovmBurnAdmin,
})
} }
deployFn.tags = ['Lib_AddressManager'] deployFn.tags = ['Lib_AddressManager']
......
...@@ -65,6 +65,12 @@ task('deploy') ...@@ -65,6 +65,12 @@ task('deploy')
undefined, undefined,
types.string types.string
) )
.addOptionalParam(
'ovmBurnAdmin',
'Address that can update gas burn parameters in the CTC. Must be provided or this deployment will fail.',
undefined,
types.string
)
.setAction(async (args, hre: any, runSuper) => { .setAction(async (args, hre: any, runSuper) => {
// Necessary because hardhat doesn't let us attach non-optional parameters to existing tasks. // Necessary because hardhat doesn't let us attach non-optional parameters to existing tasks.
const validateAddressArg = (argName: string) => { const validateAddressArg = (argName: string) => {
......
...@@ -146,7 +146,7 @@ describe('[GAS BENCHMARK] Depositing via the standard bridge', () => { ...@@ -146,7 +146,7 @@ describe('[GAS BENCHMARK] Depositing via the standard bridge', () => {
const receipt = await res.wait() const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber() const gasUsed = receipt.gasUsed.toNumber()
console.log(' - Gas used:', gasUsed) console.log(' - Gas used:', gasUsed)
expectApprox(gasUsed, 116_003, { expectApprox(gasUsed, 155_089, {
absoluteUpperDeviation: 500, absoluteUpperDeviation: 500,
// Assert a lower bound of 1% reduction on gas cost. If your tests are breaking because your // Assert a lower bound of 1% reduction on gas cost. If your tests are breaking because your
// contracts are too efficient, consider updating the target value! // contracts are too efficient, consider updating the target value!
...@@ -173,7 +173,7 @@ describe('[GAS BENCHMARK] Depositing via the standard bridge', () => { ...@@ -173,7 +173,7 @@ describe('[GAS BENCHMARK] Depositing via the standard bridge', () => {
const receipt = await res.wait() const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber() const gasUsed = receipt.gasUsed.toNumber()
console.log(' - Gas used:', gasUsed) console.log(' - Gas used:', gasUsed)
expectApprox(gasUsed, 163_844, { expectApprox(gasUsed, 202_930, {
absoluteUpperDeviation: 500, absoluteUpperDeviation: 500,
// Assert a lower bound of 1% reduction on gas cost. If your tests are breaking because your // Assert a lower bound of 1% reduction on gas cost. If your tests are breaking because your
// contracts are too efficient, consider updating the target value! // contracts are too efficient, consider updating the target value!
......
...@@ -314,7 +314,7 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => { ...@@ -314,7 +314,7 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
console.log('Benchmark complete.') console.log('Benchmark complete.')
expectApprox(gasUsed, 126_700, { expectApprox(gasUsed, 158_690, {
absoluteUpperDeviation: 500, absoluteUpperDeviation: 500,
// Assert a lower bound of 1% reduction on gas cost. If your tests are breaking because your // Assert a lower bound of 1% reduction on gas cost. If your tests are breaking because your
// contracts are too efficient, consider updating the target value! // contracts are too efficient, consider updating the target value!
......
...@@ -65,8 +65,9 @@ const appendSequencerBatch = async ( ...@@ -65,8 +65,9 @@ const appendSequencerBatch = async (
describe('CanonicalTransactionChain', () => { describe('CanonicalTransactionChain', () => {
let signer: Signer let signer: Signer
let sequencer: Signer let sequencer: Signer
let burnAdmin: Signer
before(async () => { before(async () => {
;[signer, sequencer] = await ethers.getSigners() ;[signer, sequencer, burnAdmin] = await ethers.getSigners()
}) })
let AddressManager: Contract let AddressManager: Contract
...@@ -78,6 +79,11 @@ describe('CanonicalTransactionChain', () => { ...@@ -78,6 +79,11 @@ describe('CanonicalTransactionChain', () => {
await sequencer.getAddress() await sequencer.getAddress()
) )
await AddressManager.setAddress(
'OVM_BurnAdmin',
await burnAdmin.getAddress()
)
Mock__StateCommitmentChain = await smockit( Mock__StateCommitmentChain = await smockit(
await ethers.getContractFactory('StateCommitmentChain') await ethers.getContractFactory('StateCommitmentChain')
) )
...@@ -107,7 +113,7 @@ describe('CanonicalTransactionChain', () => { ...@@ -107,7 +113,7 @@ describe('CanonicalTransactionChain', () => {
AddressManager.address, AddressManager.address,
MAX_GAS_LIMIT, MAX_GAS_LIMIT,
L2_GAS_DISCOUNT_DIVISOR, L2_GAS_DISCOUNT_DIVISOR,
ENQUEUE_GAS_COST, ENQUEUE_GAS_COST
) )
const batches = await Factory__ChainStorageContainer.deploy( const batches = await Factory__ChainStorageContainer.deploy(
...@@ -137,15 +143,15 @@ describe('CanonicalTransactionChain', () => { ...@@ -137,15 +143,15 @@ describe('CanonicalTransactionChain', () => {
describe('Gas param setters', () => { describe('Gas param setters', () => {
describe('setGasDivisor', async () => { describe('setGasDivisor', async () => {
it('should revert when not called by the sequencer', async () => { it('should revert when not called by the Burn Admin', async () => {
await expect( await expect(
CanonicalTransactionChain.connect(signer).setGasDivisor(32) CanonicalTransactionChain.connect(signer).setGasDivisor(32)
).to.be.revertedWith('Only callable by the Sequencer.') ).to.be.revertedWith('Only callable by the Burn Admin.')
}) })
it('should update the l2GasDiscountDivisor and enqueueL2GasPrepaid correctly', async () => { it('should update the l2GasDiscountDivisor and enqueueL2GasPrepaid correctly', async () => {
const newGasDivisor = 19 const newGasDivisor = 19
await CanonicalTransactionChain.connect(sequencer).setGasDivisor( await CanonicalTransactionChain.connect(burnAdmin).setGasDivisor(
newGasDivisor newGasDivisor
) )
...@@ -157,21 +163,21 @@ describe('CanonicalTransactionChain', () => { ...@@ -157,21 +163,21 @@ describe('CanonicalTransactionChain', () => {
it('should emit an L2GasParamsUpdated event', async () => { it('should emit an L2GasParamsUpdated event', async () => {
await expect( await expect(
CanonicalTransactionChain.connect(sequencer).setGasDivisor(88) CanonicalTransactionChain.connect(burnAdmin).setGasDivisor(88)
).to.emit(CanonicalTransactionChain, 'L2GasParamsUpdated') ).to.emit(CanonicalTransactionChain, 'L2GasParamsUpdated')
}) })
}) })
describe('setEnqueueGasCost', async () => { describe('setEnqueueGasCost', async () => {
it('should revert when not called by the sequencer', async () => { it('should revert when not called by the Burn Admin', async () => {
await expect( await expect(
CanonicalTransactionChain.connect(signer).setEnqueueGasCost(60000) CanonicalTransactionChain.connect(signer).setEnqueueGasCost(60000)
).to.be.revertedWith('Only callable by the Sequencer.') ).to.be.revertedWith('Only callable by the Burn Admin.')
}) })
it('should update the enqueueGasCost and enqueueL2GasPrepaid correctly', async () => { it('should update the enqueueGasCost and enqueueL2GasPrepaid correctly', async () => {
const newEnqueueGasCost = 31113 const newEnqueueGasCost = 31113
await CanonicalTransactionChain.connect(sequencer).setEnqueueGasCost( await CanonicalTransactionChain.connect(burnAdmin).setEnqueueGasCost(
newEnqueueGasCost newEnqueueGasCost
) )
...@@ -186,7 +192,7 @@ describe('CanonicalTransactionChain', () => { ...@@ -186,7 +192,7 @@ describe('CanonicalTransactionChain', () => {
it('should emit an L2GasParamsUpdated event', async () => { it('should emit an L2GasParamsUpdated event', async () => {
await expect( await expect(
CanonicalTransactionChain.connect(sequencer).setEnqueueGasCost(31514) CanonicalTransactionChain.connect(burnAdmin).setEnqueueGasCost(31514)
).to.emit(CanonicalTransactionChain, 'L2GasParamsUpdated') ).to.emit(CanonicalTransactionChain, 'L2GasParamsUpdated')
}) })
}) })
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment