Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
4a6f2c10
Unverified
Commit
4a6f2c10
authored
Oct 01, 2021
by
Maurelian
Committed by
Kelvin Fichter
Nov 10, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(contracts): add gas burn params as storage vars
parent
09fa3d1f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
170 additions
and
26 deletions
+170
-26
CanonicalTransactionChain.sol
...ntracts/contracts/L1/rollup/CanonicalTransactionChain.sol
+74
-10
ICanonicalTransactionChain.sol
...tracts/contracts/L1/rollup/ICanonicalTransactionChain.sol
+24
-1
CanonicalTransactionChain.gas.spec.ts
...contracts/L1/rollup/CanonicalTransactionChain.gas.spec.ts
+6
-6
CanonicalTransactionChain.spec.ts
...est/contracts/L1/rollup/CanonicalTransactionChain.spec.ts
+66
-9
No files found.
packages/contracts/contracts/L1/rollup/CanonicalTransactionChain.sol
View file @
4a6f2c10
...
@@ -29,9 +29,15 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
...
@@ -29,9 +29,15 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
// L2 tx gas-related
// L2 tx gas-related
uint256 constant public MIN_ROLLUP_TX_GAS = 100000;
uint256 constant public MIN_ROLLUP_TX_GAS = 100000;
uint256 constant public MAX_ROLLUP_TX_SIZE = 50000;
uint256 constant public MAX_ROLLUP_TX_SIZE = 50000;
uint256 immutable public L2_GAS_DISCOUNT_DIVISOR;
uint256 immutable public ENQUEUE_GAS_COST;
// The approximate cost of calling the enqueue function
uint256 immutable public ENQUEUE_L2_GAS_PREPAID;
uint256 public enqueueGasCost;
// The ratio of the cost of L1 gas to the cost of L2 gas
uint256 public l2GasDiscountDivisor;
// The amount of L2 gas which can be forwarded to L2 without spam prevention via 'gas burn'.
// Calculated as the product of l2GasDiscountDivisor * enqueueGasCost.
// See comments in enqueue() for further detail.
uint256 public enqueueL2GasPrepaid;
// Encoding-related (all in bytes)
// Encoding-related (all in bytes)
uint256 constant internal BATCH_CONTEXT_SIZE = 16;
uint256 constant internal BATCH_CONTEXT_SIZE = 16;
...
@@ -69,12 +75,70 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
...
@@ -69,12 +75,70 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
Lib_AddressResolver(_libAddressManager)
Lib_AddressResolver(_libAddressManager)
{
{
maxTransactionGasLimit = _maxTransactionGasLimit;
maxTransactionGasLimit = _maxTransactionGasLimit;
L2_GAS_DISCOUNT_DIVISOR
= _l2GasDiscountDivisor;
l2GasDiscountDivisor
= _l2GasDiscountDivisor;
ENQUEUE_GAS_COST
= _enqueueGasCost;
enqueueGasCost
= _enqueueGasCost;
ENQUEUE_L2_GAS_PREPAID
= _l2GasDiscountDivisor * _enqueueGasCost;
enqueueL2GasPrepaid
= _l2GasDiscountDivisor * _enqueueGasCost;
}
}
/**********************
* Function Modifiers *
**********************/
/**
* Modifier to enforce that, if configured, only the OVM_Sequencer contract may
* successfully call a method.
*/
modifier onlySequencer() {
require(
msg.sender == resolve("OVM_Sequencer"),
"Only callable by the Sequencer."
);
_;
}
/*******************************
* Authorized Setter Functions *
*******************************/
/**
* Allows the Sequencer to update the gas amount which is 'prepaid' during enqueue.
* The value of enqueueL2GasPrepaid is immediately updated as well.
*/
function setEnqueueGasCost(uint256 _enqueueGasCost)
external
onlySequencer
{
enqueueGasCost = _enqueueGasCost;
enqueueL2GasPrepaid = l2GasDiscountDivisor * _enqueueGasCost;
emit L2GasParamsUpdated(
l2GasDiscountDivisor,
enqueueGasCost,
enqueueL2GasPrepaid
);
}
/**
* Allows the Sequencer to update the L2 Gas Discount Divisor, which is defined as the ratio
* of the cost of gas on L1 to L2.
* The value of enqueueL2GasPrepaid is immediately updated as well.
*/
function setGasDivisor(uint256 _l2GasDiscountDivisor)
external
onlySequencer
{
l2GasDiscountDivisor = _l2GasDiscountDivisor;
enqueueL2GasPrepaid = _l2GasDiscountDivisor * enqueueGasCost;
emit L2GasParamsUpdated(
l2GasDiscountDivisor,
enqueueGasCost,
enqueueL2GasPrepaid
);
}
/********************
/********************
* Public Functions *
* Public Functions *
********************/
********************/
...
@@ -260,13 +324,13 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
...
@@ -260,13 +324,13 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
// Transactions submitted to the queue lack a method for paying gas fees to the Sequencer.
// Transactions submitted to the queue lack a method for paying gas fees to the Sequencer.
// So we need to prevent spam attacks by ensuring that the cost of enqueueing a transaction
// So we need to prevent spam attacks by ensuring that the cost of enqueueing a transaction
// from L1 to L2 is not underpriced. Therefore, we define '
ENQUEUE_L2_GAS_PREPAID
' as a
// from L1 to L2 is not underpriced. Therefore, we define '
enqueueL2GasPrepaid
' as a
// threshold. If the _gasLimit for the enqueued transaction is above this threshold, then we
// threshold. If the _gasLimit for the enqueued transaction is above this threshold, then we
// 'charge' to user by burning additional L1 gas. Since gas is cheaper on L2 than L1, we
// 'charge' to user by burning additional L1 gas. Since gas is cheaper on L2 than L1, we
// only need to burn a fraction of the provided L1 gas, which is determined by the
// only need to burn a fraction of the provided L1 gas, which is determined by the
//
L2_GAS_DISCOUNT_DIVISOR
.
//
l2GasDiscountDivisor
.
if(_gasLimit >
ENQUEUE_L2_GAS_PREPAID
) {
if(_gasLimit >
enqueueL2GasPrepaid
) {
uint256 gasToConsume = (_gasLimit -
ENQUEUE_L2_GAS_PREPAID) / L2_GAS_DISCOUNT_DIVISOR
;
uint256 gasToConsume = (_gasLimit -
enqueueL2GasPrepaid) / l2GasDiscountDivisor
;
uint256 startingGas = gasleft();
uint256 startingGas = gasleft();
// Although this check is not necessary (burn below will run out of gas if not true), it
// Although this check is not necessary (burn below will run out of gas if not true), it
...
...
packages/contracts/contracts/L1/rollup/ICanonicalTransactionChain.sol
View file @
4a6f2c10
...
@@ -16,6 +16,12 @@ interface ICanonicalTransactionChain {
...
@@ -16,6 +16,12 @@ interface ICanonicalTransactionChain {
* Events *
* Events *
**********/
**********/
event L2GasParamsUpdated(
uint256 l2GasDiscountDivisor,
uint256 enqueueGasCost,
uint256 enqueueL2GasPrepaid
);
event TransactionEnqueued(
event TransactionEnqueued(
address indexed _l1TxOrigin,
address indexed _l1TxOrigin,
address indexed _target,
address indexed _target,
...
@@ -57,12 +63,29 @@ interface ICanonicalTransactionChain {
...
@@ -57,12 +63,29 @@ interface ICanonicalTransactionChain {
uint256 blockNumber;
uint256 blockNumber;
}
}
/*******************************
* Authorized Setter Functions *
*******************************/
/**
* Allows the Sequencer to update the gas amount which is 'prepaid' during enqueue.
* The value of enqueueL2GasPrepaid is immediately updated as well.
*/
function setEnqueueGasCost(uint256 _enqueueGasCost)
external;
/**
* Allows the Sequencer to update the L2 Gas Discount Divisor, which is defined as the ratio
* of the cost of gas on L1 to L2.
* The value of enqueueL2GasPrepaid is immediately updated as well.
*/
function setGasDivisor(uint256 _l2GasDiscountDivisor)
external;
/********************
/********************
* Public Functions *
* Public Functions *
********************/
********************/
/**
/**
* Accesses the batch storage container.
* Accesses the batch storage container.
* @return Reference to the batch storage container.
* @return Reference to the batch storage container.
...
...
packages/contracts/test/contracts/L1/rollup/CanonicalTransactionChain.gas.spec.ts
View file @
4a6f2c10
...
@@ -271,17 +271,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
...
@@ -271,17 +271,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
})
})
describe
(
'
enqueue [ @skip-on-coverage ]
'
,
()
=>
{
describe
(
'
enqueue [ @skip-on-coverage ]
'
,
()
=>
{
let
ENQUEUE_L2_GAS_PREPAID
let
enqueueL2GasPrepaid
let
data
let
data
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
CanonicalTransactionChain
=
CanonicalTransactionChain
.
connect
(
sequencer
)
CanonicalTransactionChain
=
CanonicalTransactionChain
.
connect
(
sequencer
)
ENQUEUE_L2_GAS_PREPAID
=
enqueueL2GasPrepaid
=
await
CanonicalTransactionChain
.
ENQUEUE_L2_GAS_PREPAID
()
await
CanonicalTransactionChain
.
enqueueL2GasPrepaid
()
data
=
'
0x
'
+
'
12
'
.
repeat
(
1234
)
data
=
'
0x
'
+
'
12
'
.
repeat
(
1234
)
})
})
it
(
'
cost to enqueue a transaction above the prepaid threshold
'
,
async
()
=>
{
it
(
'
cost to enqueue a transaction above the prepaid threshold
'
,
async
()
=>
{
const
l2GasLimit
=
2
*
ENQUEUE_L2_GAS_PREPAID
const
l2GasLimit
=
2
*
enqueueL2GasPrepaid
const
res
=
await
CanonicalTransactionChain
.
enqueue
(
const
res
=
await
CanonicalTransactionChain
.
enqueue
(
NON_ZERO_ADDRESS
,
NON_ZERO_ADDRESS
,
...
@@ -293,7 +293,7 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
...
@@ -293,7 +293,7 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
console
.
log
(
'
Benchmark complete.
'
)
console
.
log
(
'
Benchmark complete.
'
)
expectApprox
(
gasUsed
,
187
_081
,
{
expectApprox
(
gasUsed
,
220
_677
,
{
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!
...
@@ -302,7 +302,7 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
...
@@ -302,7 +302,7 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
})
})
it
(
'
cost to enqueue a transaction below the prepaid threshold
'
,
async
()
=>
{
it
(
'
cost to enqueue a transaction below the prepaid threshold
'
,
async
()
=>
{
const
l2GasLimit
=
ENQUEUE_L2_GAS_PREPAID
-
1
const
l2GasLimit
=
enqueueL2GasPrepaid
-
1
const
res
=
await
CanonicalTransactionChain
.
enqueue
(
const
res
=
await
CanonicalTransactionChain
.
enqueue
(
NON_ZERO_ADDRESS
,
NON_ZERO_ADDRESS
,
...
...
packages/contracts/test/contracts/L1/rollup/CanonicalTransactionChain.spec.ts
View file @
4a6f2c10
...
@@ -107,7 +107,7 @@ describe('CanonicalTransactionChain', () => {
...
@@ -107,7 +107,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
(
...
@@ -135,6 +135,63 @@ describe('CanonicalTransactionChain', () => {
...
@@ -135,6 +135,63 @@ describe('CanonicalTransactionChain', () => {
)
)
})
})
describe
(
'
Gas param setters
'
,
()
=>
{
describe
(
'
setGasDivisor
'
,
async
()
=>
{
it
(
'
should revert when not called by the sequencer
'
,
async
()
=>
{
await
expect
(
CanonicalTransactionChain
.
connect
(
signer
).
setGasDivisor
(
32
)
).
to
.
be
.
revertedWith
(
'
Only callable by the Sequencer.
'
)
})
it
(
'
should update the l2GasDiscountDivisor and enqueueL2GasPrepaid correctly
'
,
async
()
=>
{
const
newGasDivisor
=
19
await
CanonicalTransactionChain
.
connect
(
sequencer
).
setGasDivisor
(
newGasDivisor
)
const
enqueueGasCost
=
await
CanonicalTransactionChain
.
enqueueGasCost
()
const
enqueueL2GasPrepaid
=
await
CanonicalTransactionChain
.
enqueueL2GasPrepaid
()
expect
(
enqueueL2GasPrepaid
).
to
.
equal
(
newGasDivisor
*
enqueueGasCost
)
})
it
(
'
should emit an L2GasParamsUpdated event
'
,
async
()
=>
{
await
expect
(
CanonicalTransactionChain
.
connect
(
sequencer
).
setGasDivisor
(
88
)
).
to
.
emit
(
CanonicalTransactionChain
,
'
L2GasParamsUpdated
'
)
})
})
describe
(
'
setEnqueueGasCost
'
,
async
()
=>
{
it
(
'
should revert when not called by the sequencer
'
,
async
()
=>
{
await
expect
(
CanonicalTransactionChain
.
connect
(
signer
).
setEnqueueGasCost
(
60000
)
).
to
.
be
.
revertedWith
(
'
Only callable by the Sequencer.
'
)
})
it
(
'
should update the enqueueGasCost and enqueueL2GasPrepaid correctly
'
,
async
()
=>
{
const
newEnqueueGasCost
=
31113
await
CanonicalTransactionChain
.
connect
(
sequencer
).
setEnqueueGasCost
(
newEnqueueGasCost
)
const
l2GasDiscountDivisor
=
await
CanonicalTransactionChain
.
l2GasDiscountDivisor
()
const
enqueueL2GasPrepaid
=
await
CanonicalTransactionChain
.
enqueueL2GasPrepaid
()
expect
(
enqueueL2GasPrepaid
).
to
.
equal
(
l2GasDiscountDivisor
*
newEnqueueGasCost
)
})
it
(
'
should emit an L2GasParamsUpdated event
'
,
async
()
=>
{
await
expect
(
CanonicalTransactionChain
.
connect
(
sequencer
).
setEnqueueGasCost
(
31514
)
).
to
.
emit
(
CanonicalTransactionChain
,
'
L2GasParamsUpdated
'
)
})
})
})
describe
(
'
enqueue
'
,
()
=>
{
describe
(
'
enqueue
'
,
()
=>
{
const
target
=
NON_ZERO_ADDRESS
const
target
=
NON_ZERO_ADDRESS
const
gasLimit
=
500
_000
const
gasLimit
=
500
_000
...
@@ -176,9 +233,9 @@ describe('CanonicalTransactionChain', () => {
...
@@ -176,9 +233,9 @@ describe('CanonicalTransactionChain', () => {
it
(
'
should revert if transaction gas limit does not cover rollup burn
'
,
async
()
=>
{
it
(
'
should revert if transaction gas limit does not cover rollup burn
'
,
async
()
=>
{
const
_enqueueL2GasPrepaid
=
const
_enqueueL2GasPrepaid
=
await
CanonicalTransactionChain
.
ENQUEUE_L2_GAS_PREPAID
()
await
CanonicalTransactionChain
.
enqueueL2GasPrepaid
()
const
l2GasDiscountDivisor
=
const
l2GasDiscountDivisor
=
await
CanonicalTransactionChain
.
L2_GAS_DISCOUNT_DIVISOR
()
await
CanonicalTransactionChain
.
l2GasDiscountDivisor
()
const
data
=
'
0x
'
+
'
12
'
.
repeat
(
1234
)
const
data
=
'
0x
'
+
'
12
'
.
repeat
(
1234
)
// Create a tx with high L2 gas limit, but insufficient L1 gas limit to cover burn.
// Create a tx with high L2 gas limit, but insufficient L1 gas limit to cover burn.
...
@@ -187,7 +244,7 @@ describe('CanonicalTransactionChain', () => {
...
@@ -187,7 +244,7 @@ describe('CanonicalTransactionChain', () => {
// additional gas overhead, it will be enough trigger the gas burn, but not enough to cover
// additional gas overhead, it will be enough trigger the gas burn, but not enough to cover
// it.
// it.
const
l1GasLimit
=
const
l1GasLimit
=
(
l2GasLimit
-
_enqueueL2GasPrepaid
)
/
l2GasDiscountDivisor
(
l2GasLimit
-
_enqueueL2GasPrepaid
)
/
l2GasDiscountDivisor
await
expect
(
await
expect
(
CanonicalTransactionChain
.
enqueue
(
target
,
l2GasLimit
,
data
,
{
CanonicalTransactionChain
.
enqueue
(
target
,
l2GasLimit
,
data
,
{
...
@@ -223,13 +280,13 @@ describe('CanonicalTransactionChain', () => {
...
@@ -223,13 +280,13 @@ describe('CanonicalTransactionChain', () => {
})
})
})
})
describe
(
'
with _gaslimit below the
ENQUEUE_L2_GAS_PREPAID
threshold
'
,
async
()
=>
{
describe
(
'
with _gaslimit below the
enqueueL2GasPrepaid
threshold
'
,
async
()
=>
{
it
(
'
the cost to enqueue transactions is consistent for different L2 gas amounts below the prepaid threshold
'
,
async
()
=>
{
it
(
'
the cost to enqueue transactions is consistent for different L2 gas amounts below the prepaid threshold
'
,
async
()
=>
{
const
ENQUEUE_L2_GAS_PREPAID
=
const
enqueueL2GasPrepaid
=
await
CanonicalTransactionChain
.
ENQUEUE_L2_GAS_PREPAID
()
await
CanonicalTransactionChain
.
enqueueL2GasPrepaid
()
const
data
=
'
0x
'
+
'
12
'
.
repeat
(
1234
)
const
data
=
'
0x
'
+
'
12
'
.
repeat
(
1234
)
const
l2GasLimit1
=
ENQUEUE_L2_GAS_PREPAID
-
1
const
l2GasLimit1
=
enqueueL2GasPrepaid
-
1
const
l2GasLimit2
=
ENQUEUE_L2_GAS_PREPAID
-
100
const
l2GasLimit2
=
enqueueL2GasPrepaid
-
100
// The first enqueue is more expensive because it's writing to an empty slot,
// The first enqueue is more expensive because it's writing to an empty slot,
// so we need to pre-load the buffer or the test will fail.
// so we need to pre-load the buffer or the test will fail.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment