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 = (
expect(
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
expect(
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
}
......
......@@ -21,6 +21,7 @@ import {
getEthTime,
getNextBlockNumber,
NON_ZERO_ADDRESS,
expectApprox,
} from '../../../helpers'
// Still have some duplication from CanonicalTransactionChain.spec.ts, but it's so minimal that
......@@ -152,14 +153,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
})
const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber())
console.log('Gas used:', gasUsed)
console.log('Fixed calldata cost:', fixedCalldataCost)
console.log(
'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)
it('200 transactions in 200 contexts', async () => {
......@@ -192,14 +196,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
})
const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber())
console.log('Gas used:', gasUsed)
console.log('Fixed calldata cost:', fixedCalldataCost)
console.log(
'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)
it('100 Sequencer transactions and 100 Queue transactions in 100 contexts', async () => {
......@@ -242,14 +249,17 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
})
const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
console.log('Benchmark complete.')
console.log('Gas used:', receipt.gasUsed.toNumber())
console.log('Gas used:', gasUsed)
console.log('Fixed calldata cost:', fixedCalldataCost)
console.log(
'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)
})
......@@ -272,9 +282,12 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
data
)
const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
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 () => {
......@@ -286,9 +299,12 @@ describe('[GAS BENCHMARK] CanonicalTransactionChain', () => {
data
)
const receipt = await res.wait()
const gasUsed = receipt.gasUsed.toNumber()
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 { Contract, Signer } from 'ethers'
import { BigNumber, Contract, Signer } from 'ethers'
export class GasMeasurement {
GasMeasurementContract: Contract
......@@ -24,3 +25,39 @@ export class GasMeasurement {
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