Commit 541e820d authored by Maurelian's avatar Maurelian Committed by Kelvin Fichter

test(contracts): Assert upper bound on CTC gas costs.

Previously our gas specs have only printed the values they record,
without ensuring that the cost doesn't drift up over time. Adding expectApprox will allow these costs to decrease, but not increase.
parent 2a731e0d
...@@ -182,11 +182,11 @@ export const expectApprox = ( ...@@ -182,11 +182,11 @@ export const expectApprox = (
expect( expect(
actual.lte(upper), actual.lte(upper),
`Actual value is more than ${upperPercentDeviation}% greater than target` `Actual value (${actual}) is more than ${upperPercentDeviation}% greater than target (${target})`
).to.be.true ).to.be.true
expect( expect(
actual.gte(lower), actual.gte(lower),
`Actual value is more than ${lowerPercentDeviation}% less than target` `Actual value (${actual}) is more than ${lowerPercentDeviation}% less than target (${target})`
).to.be.true ).to.be.true
} }
......
...@@ -21,6 +21,7 @@ import { ...@@ -21,6 +21,7 @@ import {
getEthTime, getEthTime,
getNextBlockNumber, getNextBlockNumber,
NON_ZERO_ADDRESS, NON_ZERO_ADDRESS,
expectApprox,
} from '../../../helpers' } from '../../../helpers'
// Still have some duplication from CanonicalTransactionChain.spec.ts, but it's so minimal that // Still have some duplication from CanonicalTransactionChain.spec.ts, but it's so minimal that
...@@ -152,14 +153,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => { ...@@ -152,14 +153,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
}) })
const receipt = await res.wait() const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.') console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber()) console.log('Gas used:', gasUsed)
console.log('Fixed calldata cost:', fixedCalldataCost) console.log('Fixed calldata cost:', fixedCalldataCost)
console.log( console.log(
'Non-calldata overhead gas cost per transaction:', 'Non-calldata overhead gas cost per transaction:',
(receipt.gasUsed.toNumber() - fixedCalldataCost) / numTxs (gasUsed - fixedCalldataCost) / numTxs
) )
expectApprox(gasUsed, 1_605_796, { upperPercentDeviation: 0 })
}).timeout(10_000_000) }).timeout(10_000_000)
it('200 transactions in 200 contexts', async () => { it('200 transactions in 200 contexts', async () => {
...@@ -192,14 +196,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => { ...@@ -192,14 +196,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
}) })
const receipt = await res.wait() const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.') console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber()) console.log('Gas used:', gasUsed)
console.log('Fixed calldata cost:', fixedCalldataCost) console.log('Fixed calldata cost:', fixedCalldataCost)
console.log( console.log(
'Non-calldata overhead gas cost per transaction:', 'Non-calldata overhead gas cost per transaction:',
(receipt.gasUsed.toNumber() - fixedCalldataCost) / numTxs (gasUsed - fixedCalldataCost) / numTxs
) )
expectApprox(gasUsed, 1_739_811, { upperPercentDeviation: 0 })
}).timeout(10_000_000) }).timeout(10_000_000)
it('100 Sequencer transactions and 100 Queue transactions in 100 contexts', async () => { it('100 Sequencer transactions and 100 Queue transactions in 100 contexts', async () => {
...@@ -242,14 +249,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => { ...@@ -242,14 +249,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
}) })
const receipt = await res.wait() const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.') console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber()) console.log('Gas used:', gasUsed)
console.log('Fixed calldata cost:', fixedCalldataCost) console.log('Fixed calldata cost:', fixedCalldataCost)
console.log( console.log(
'Non-calldata overhead gas cost per transaction:', 'Non-calldata overhead gas cost per transaction:',
(receipt.gasUsed.toNumber() - fixedCalldataCost) / numTxs (gasUsed - fixedCalldataCost) / numTxs
) )
expectApprox(gasUsed, 1_126_553, { upperPercentDeviation: 0 })
}).timeout(10_000_000) }).timeout(10_000_000)
}) })
...@@ -272,9 +282,12 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => { ...@@ -272,9 +282,12 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
data data
) )
const receipt = await res.wait() const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.') console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber()) console.log('Gas used:', gasUsed)
expectApprox(gasUsed, 217_615, { upperPercentDeviation: 0 })
}) })
it('cost to enqueue a transaction below the prepaid threshold', async () => { it('cost to enqueue a transaction below the prepaid threshold', async () => {
...@@ -286,9 +299,12 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => { ...@@ -286,9 +299,12 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
data data
) )
const receipt = await res.wait() const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.') console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber()) console.log('Gas used:', gasUsed)
expectApprox(gasUsed, 156_711, { upperPercentDeviation: 0 })
}) })
}) })
}) })
import { expect } from 'chai'
import { ethers } from 'hardhat' import { ethers } from 'hardhat'
import { Contract, Signer } from 'ethers' import { BigNumber, Contract, Signer } from 'ethers'
export class GasMeasurement { export class GasMeasurement {
GasMeasurementContract: Contract GasMeasurementContract: Contract
...@@ -24,3 +25,39 @@ export class GasMeasurement { ...@@ -24,3 +25,39 @@ export class GasMeasurement {
return gasCost return gasCost
} }
} }
interface percentDeviationRange {
upperPercentDeviation: number
lowerPercentDeviation?: number
}
export const expectApprox = (
actual: BigNumber | number,
target: BigNumber | number,
{ upperPercentDeviation, lowerPercentDeviation = 100 }: percentDeviationRange
): void => {
actual = BigNumber.from(actual)
target = BigNumber.from(target)
const validDeviations =
upperPercentDeviation >= 0 &&
upperPercentDeviation <= 100 &&
lowerPercentDeviation >= 0 &&
lowerPercentDeviation <= 100
if (!validDeviations) {
throw new Error(
'Upper and lower deviation percentage arguments should be between 0 and 100'
)
}
const upper = target.mul(100 + upperPercentDeviation).div(100)
const lower = target.mul(100 - lowerPercentDeviation).div(100)
expect(
actual.lte(upper),
`Actual value (${actual}) is more than ${upperPercentDeviation}% greater than target (${target})`
).to.be.true
expect(
actual.gte(lower),
`Actual value (${actual}) is more than ${lowerPercentDeviation}% less than target (${target})`
).to.be.true
}
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