Skip to content

Commit

Permalink
add simulation gas test (#519)
Browse files Browse the repository at this point in the history
verify that simulation verificationGasLimit is above execution
(handleOps) verificationGasLimit
(add a test without a paymaster)
  • Loading branch information
drortirosh authored Dec 23, 2024
1 parent ba985b9 commit 720ce6d
Showing 1 changed file with 71 additions and 58 deletions.
129 changes: 71 additions & 58 deletions test/entrypointsimulations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,71 +247,84 @@ describe('EntryPointSimulations', function () {
})
})

describe('over-validation test', () => {
// coverage skews gas checks.
if (process.env.COVERAGE != null) {
return
}

let vgl: number
let pmVgl: number
let paymaster: TestPaymasterWithPostOp
let sender: string
let owner: Wallet
async function userOpWithGas (vgl: number, pmVgl = 0): Promise<UserOperation> {
return fillAndSign({
sender,
verificationGasLimit: vgl,
paymaster: pmVgl !== 0 ? paymaster.address : undefined,
paymasterVerificationGasLimit: pmVgl,
paymasterPostOpGasLimit: pmVgl,
maxFeePerGas: 1,
maxPriorityFeePerGas: 1
}, owner, entryPoint)
}
before(async () => {
owner = createAccountOwner()
paymaster = await new TestPaymasterWithPostOp__factory(ethersSigner).deploy(entryPoint.address)
await entryPoint.depositTo(paymaster.address, { value: parseEther('1') })
const { proxy: account } = await createAccount(ethersSigner, owner.address, entryPoint.address)
sender = account.address
await fund(account)
pmVgl = await findSimulationUserOpWithMin(async n => userOpWithGas(1e6, n), entryPoint, 1, 500000)
vgl = await findSimulationUserOpWithMin(async n => userOpWithGas(n, pmVgl), entryPoint, 3000, 500000)
// parameterize this test on paymaster true/false:
for (const withPaymaster of ['with', 'without']) {
describe(`over-validation test ${withPaymaster} paymaster`, () => {
// coverage skews gas checks.
if (process.env.COVERAGE != null) {
return
}

const userOp = await userOpWithGas(vgl, pmVgl)
let vgl: number
let pmVgl: number
let paymaster: TestPaymasterWithPostOp
let sender: string
let owner: Wallet

async function userOpWithGas (vgl: number, pmVgl = 0): Promise<UserOperation> {
return fillAndSign({
sender,
verificationGasLimit: vgl,
paymaster: pmVgl !== 0 ? paymaster.address : undefined,
paymasterVerificationGasLimit: pmVgl,
paymasterPostOpGasLimit: pmVgl,
maxFeePerGas: 1,
maxPriorityFeePerGas: 1
}, owner, entryPoint)
}

await simulateValidation(packUserOp(userOp), entryPoint.address)
.catch(e => { throw new Error(decodeRevertReason(e)!) })
})
describe('compare to execution', () => {
let execVgl: number
let execPmVgl: number
const diff = 2000
before(async () => {
execPmVgl = await findUserOpWithMin(async n => userOpWithGas(1e6, n), false, entryPoint, 1, 500000)
execVgl = await findUserOpWithMin(async n => userOpWithGas(n, execPmVgl), false, entryPoint, 1, 500000)
owner = createAccountOwner()
paymaster = await new TestPaymasterWithPostOp__factory(ethersSigner).deploy(entryPoint.address)
await entryPoint.depositTo(paymaster.address, { value: parseEther('1') })
const { proxy: account } = await createAccount(ethersSigner, owner.address, entryPoint.address)
sender = account.address
await fund(account)
pmVgl = withPaymaster === 'without' ? 0 : await findSimulationUserOpWithMin(async n => userOpWithGas(1e6, n), entryPoint, 1, 500000)
vgl = await findSimulationUserOpWithMin(async n => userOpWithGas(n, pmVgl), entryPoint, 3000, 500000)

const userOp = await userOpWithGas(vgl, pmVgl)

await simulateValidation(packUserOp(userOp), entryPoint.address)
.catch(e => {
throw new Error(decodeRevertReason(e)!)
})
})
it('account verification simulation cost should be higher than execution', function () {
console.log('simulation account validation', vgl, 'above exec:', vgl - execVgl)
expect(vgl).to.be.within(execVgl + 1, execVgl + diff, `expected simulation verificationGas to be 1..${diff} above actual, but was ${vgl - execVgl}`)

describe(`compare to execution ${withPaymaster} paymaster`, () => {
let execVgl: number
let execPmVgl: number
const diff = 2000
before(async () => {
execPmVgl = withPaymaster === 'without' ? 0 : await findUserOpWithMin(async n => userOpWithGas(1e6, n), false, entryPoint, 1, 500000)
execVgl = await findUserOpWithMin(async n => userOpWithGas(n, execPmVgl), false, entryPoint, 1, 500000)
})
it(`account verification simulation cost should be higher than execution ${withPaymaster} paymaster`, function () {
console.log('simulation account validation', vgl, 'above exec:', vgl - execVgl)
expect(vgl).to.be.within(execVgl + 1, execVgl + diff, `expected simulation verificationGas to be 1..${diff} above actual, but was ${vgl - execVgl}`)
})
if (withPaymaster === 'with') {
it('paymaster verification simulation cost should be higher than execution', function () {
console.log('simulation paymaster validation', pmVgl, 'above exec:', pmVgl - execPmVgl)
expect(pmVgl).to.be.within(execPmVgl + 1, execPmVgl + diff, `expected simulation verificationGas to be 1..${diff} above actual, but was ${pmVgl - execPmVgl}`)
})
}
})
it('paymaster verification simulation cost should be higher than execution', function () {
console.log('simulation paymaster validation', pmVgl, 'above exec:', pmVgl - execPmVgl)
expect(pmVgl).to.be.within(execPmVgl + 1, execPmVgl + diff, `expected simulation verificationGas to be 1..${diff} above actual, but was ${pmVgl - execPmVgl}`)

it('should revert with AA2x if verificationGasLimit is low', async function () {
expect(await simulateValidation(packUserOp(await userOpWithGas(vgl - 1, pmVgl)), entryPoint.address)
.catch(decodeRevertReason))
.to.match(/AA26/)
})
if (withPaymaster === 'with') {
it('should revert with AA3x if paymasterVerificationGasLimit is low', async function () {
expect(await simulateValidation(packUserOp(await userOpWithGas(vgl, pmVgl - 1)), entryPoint.address)
.catch(decodeRevertReason))
.to.match(/AA36/)
})
}
})
it('should revert with AA2x if verificationGasLimit is low', async function () {
expect(await simulateValidation(packUserOp(await userOpWithGas(vgl - 1, pmVgl)), entryPoint.address)
.catch(decodeRevertReason))
.to.match(/AA26/)
})
it('should revert with AA3x if paymasterVerificationGasLimit is low', async function () {
expect(await simulateValidation(packUserOp(await userOpWithGas(vgl, pmVgl - 1)), entryPoint.address)
.catch(decodeRevertReason))
.to.match(/AA36/)
})
})
}

describe('#simulateHandleOp', () => {
it('should simulate creation', async () => {
Expand Down

0 comments on commit 720ce6d

Please sign in to comment.