Skip to content

Commit

Permalink
verify that EntryPoint calls never cost less during simulation (#328)
Browse files Browse the repository at this point in the history
  • Loading branch information
drortirosh authored Aug 17, 2023
1 parent 17e39df commit 887bfab
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 22 deletions.
6 changes: 6 additions & 0 deletions contracts/core/EntryPointSimulations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,10 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {
// always revert
revert("");
}

//make sure depositTo cost is more than normal EntryPoint's cost.
// empiric test showed that without this wrapper, simulation depositTo costs less..
function depositTo(address account) public override(IStakeManager, StakeManager) payable {
StakeManager.depositTo(account);
}
}
2 changes: 1 addition & 1 deletion contracts/core/StakeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ abstract contract StakeManager is IStakeManager {
* Add to the deposit of the given account.
* @param account - The account to add to.
*/
function depositTo(address account) public payable {
function depositTo(address account) public virtual payable {
_incrementDeposit(account, msg.value);
DepositInfo storage info = deposits[account];
emit Deposited(account, info.deposit);
Expand Down
28 changes: 14 additions & 14 deletions reports/gas-checker.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,38 @@
the destination is "account.entryPoint()", which is known to be "hot" address used by this account
it little higher than EOA call: its an exec from entrypoint (or account owner) into account contract, verifying msg.sender and exec to target)
╔══════════════════════════╤════════╗
║ gas estimate "simple" │ 29014
║ gas estimate "simple" │ 29002
╟──────────────────────────┼────────╢
║ gas estimate "big tx 5k" │ 125248
║ gas estimate "big tx 5k" │ 125260
╚══════════════════════════╧════════╝

╔════════════════════════════════╤═══════╤═══════════════╤════════════════╤═════════════════════╗
║ handleOps description │ count │ total gasUsed │ per UserOp gas │ per UserOp overhead ║
║ │ │ │ (delta for │ (compared to ║
║ │ │ │ one UserOp) │ account.exec()) ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple │ 1 │ 81910 │ │ ║
║ simple │ 1 │ 81886 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple - diff from previous │ 2 │ │ 44189 │ 15175
║ simple - diff from previous │ 2 │ │ 44189 │ 15187
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple │ 10 │ 479752 │ │ ║
║ simple │ 10 │ 479680 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple - diff from previous │ 11 │ │ 4417715163
║ simple - diff from previous │ 11 │ │ 4426115259
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster │ 1 │ 88193 │ │ ║
║ simple paymaster │ 1 │ 88181 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster with diff │ 2 │ │ 4315414140
║ simple paymaster with diff │ 2 │ │ 4317814176
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster │ 10 │ 476928 │ │ ║
║ simple paymaster │ 10 │ 476964 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster with diff │ 11 │ │ 4323714223
║ simple paymaster with diff │ 11 │ │ 4318914187
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx 5k │ 1 │ 182943 │ │ ║
║ big tx 5k │ 1 │ 182967 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx - diff from previous │ 2 │ │ 144700 │ 19452
║ big tx - diff from previous │ 2 │ │ 144700 │ 19440
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx 5k │ 10 │ 1485360 │ │ ║
║ big tx 5k │ 10 │ 1485396 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx - diff from previous │ 11 │ │ 144725 │ 19477
║ big tx - diff from previous │ 11 │ │ 144725 │ 19465
╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝

Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { ethers } from 'hardhat'
import { expect } from 'chai'

import {
EntryPoint,
EntryPoint, EntryPointSimulations, EntryPointSimulations__factory,
SimpleAccount,
SimpleAccountFactory,
TestCounter__factory
} from '../../typechain'
} from '../typechain'
import {
ONE_ETH,
createAccount,
Expand All @@ -17,12 +17,13 @@ import {
getAccountAddress,
getAccountInitCode,
getBalance
} from '../testutils'
} from './testutils'

import { fillAndSign, simulateHandleOp, simulateValidation } from '../UserOp'
import { fillAndSign, simulateHandleOp, simulateValidation } from './UserOp'
import { BigNumber, Wallet } from 'ethers'
import { hexConcat } from 'ethers/lib/utils'

const provider = ethers.provider
describe('EntryPointSimulations', function () {
const ethersSigner = ethers.provider.getSigner()

Expand All @@ -31,12 +32,11 @@ describe('EntryPointSimulations', function () {
let simpleAccountFactory: SimpleAccountFactory

let entryPoint: EntryPoint
let epSimulation: EntryPointSimulations

before(async function () {
// if (network.name !== 'anvil') {
// this.skip()
// }
entryPoint = await deployActualEntryPoint()
epSimulation = await new EntryPointSimulations__factory(provider.getSigner()).deploy()

accountOwner = createAccountOwner();
({
Expand All @@ -47,6 +47,26 @@ describe('EntryPointSimulations', function () {
// await checkStateDiffSupported()
})

describe('Simulation Contract Sannity checks', () => {
const addr = createAddress()

it('deposit on simulation must be >= real entrypoint', async () => {
expect(await epSimulation.estimateGas.depositTo(addr, { value: 1 }))
.to.be.gte(await entryPoint.estimateGas.depositTo(addr, { value: 1 }), 'sim depositTo must be higher')
})
it('deposit without value on simulation must be >= real entrypoint', async () => {
expect(await epSimulation.estimateGas.depositTo(addr, { value: 0 }))
.to.be.gte(await entryPoint.estimateGas.depositTo(addr, { value: 0 }), 'sim depositTo (even without value) must be higher')
})
it('eth transfer on simulation must be >= real entrypoint', async () => {
expect(await provider.estimateGas({ to: epSimulation.address, value: 1 }))
.to.be.gte(await provider.estimateGas({ to: entryPoint.address, value: 1 }))
})
it('eth transfer (even without value) on simulation must be >= real entrypoint', async () => {
expect(await provider.estimateGas({ to: epSimulation.address, value: 0 }))
.to.be.gte(await provider.estimateGas({ to: entryPoint.address, value: 0 }))
})
})
/*
async function checkStateDiffSupported (): Promise<void> {
const tx: TransactionRequest = {
Expand Down

0 comments on commit 887bfab

Please sign in to comment.