Skip to content

Commit

Permalink
Write contract names and transaction hashes to a JSON file; skip irre…
Browse files Browse the repository at this point in the history
…levant
  • Loading branch information
forshtat committed Apr 7, 2024
1 parent b1ab6e1 commit 95e7af9
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 9 deletions.
9 changes: 7 additions & 2 deletions gascalc/1-simple-wallet.gas.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { GasChecker } from './GasChecker'
import { GasCheckCollector, GasChecker } from './GasChecker'

context('simple account', function () {
this.timeout(60000)
const g = new GasChecker()

before(async function () {
await GasCheckCollector.init()
GasCheckCollector.inst.createJsonResult = true
})

it('simple 1', async function () {
await g.addTestRow({ title: 'simple', count: 1, diffLastGas: false })
await g.addTestRow({ title: 'simple - diff from previous', count: 2, diffLastGas: true })
})

it('simple 10', async function () {
it.skip('simple 10', async function () {
if (g.skipLong()) this.skip()
await g.addTestRow({ title: 'simple', count: 10, diffLastGas: false })
await g.addTestRow({ title: 'simple - diff from previous', count: 11, diffLastGas: true })
Expand Down
45 changes: 45 additions & 0 deletions gascalc/4-paymaster-postop.gas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { parseEther } from 'ethers/lib/utils'
import { TestPaymasterWithPostOp__factory } from '../typechain'
import { ethers } from 'hardhat'
import { GasChecker } from './GasChecker'
import { Create2Factory } from '../src/Create2Factory'
import { hexValue } from '@ethersproject/bytes'

const ethersSigner = ethers.provider.getSigner()

context.skip('Paymaster with PostOp', function () {
this.timeout(60000)
const g = new GasChecker()

let paymasterAddress: string

before(async () => {
const paymasterInit = hexValue(new TestPaymasterWithPostOp__factory(ethersSigner).getDeployTransaction(g.entryPoint().address).data!)
paymasterAddress = await new Create2Factory(ethers.provider, ethersSigner).deploy(paymasterInit, 0)
const paymaster = TestPaymasterWithPostOp__factory.connect(paymasterAddress, ethersSigner)
await paymaster.addStake(1, { value: 1 })
await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') })
})

it('paymaster with PostOp', async function () {
await g.addTestRow({ title: 'paymaster+postOp', count: 1, paymaster: paymasterAddress, diffLastGas: false })
await g.addTestRow({
title: 'paymaster+postOp with diff',
count: 2,
paymaster: paymasterAddress,
diffLastGas: true
})
})

it('paymaster with postOp 10', async function () {
if (g.skipLong()) this.skip()

await g.addTestRow({ title: 'paymaster+postOp', count: 10, paymaster: paymasterAddress, diffLastGas: false })
await g.addTestRow({
title: 'paymaster+postOp with diff',
count: 11,
paymaster: paymasterAddress,
diffLastGas: true
})
})
})
133 changes: 133 additions & 0 deletions gascalc/5-token-paymaster.gas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { parseEther } from 'ethers/lib/utils'
import {
TestERC20__factory, TestOracle2__factory,
TestUniswap__factory,
TestWrappedNativeToken__factory, TokenPaymaster,
TokenPaymaster__factory
} from '../typechain'
import { ethers } from 'hardhat'
import { GasCheckCollector, GasChecker } from './GasChecker'
import { Create2Factory } from '../src/Create2Factory'
import { hexValue } from '@ethersproject/bytes'
import {
OracleHelper as OracleHelperNamespace,
UniswapHelper as UniswapHelperNamespace
} from '../typechain/contracts/samples/TokenPaymaster'
import { BigNumber } from 'ethers'
import { createAccountOwner } from '../test/testutils'
// const ethersSigner = ethers.provider.getSigner()

context.skip('Token Paymaster', function () {
this.timeout(60000)
const g = new GasChecker()

let paymasterAddress: string
before(async () => {
await GasCheckCollector.init()
const globalSigner = ethers.provider.getSigner()
const create2Factory = new Create2Factory(ethers.provider, globalSigner)

const ethersSigner = createAccountOwner()
await globalSigner.sendTransaction({ to: ethersSigner.getAddress(), value: parseEther('10') })

const minEntryPointBalance = 1e17.toString()
const initialPriceToken = 100000000 // USD per TOK
const initialPriceEther = 500000000 // USD per ETH
const priceDenominator = BigNumber.from(10).pow(26)

const tokenInit = await new TestERC20__factory(ethersSigner).getDeployTransaction(6)
const tokenAddress = await create2Factory.deploy(tokenInit, 0)
const token = TestERC20__factory.connect(tokenAddress, ethersSigner)

const wethInit = await new TestWrappedNativeToken__factory(ethersSigner).getDeployTransaction()
const wethAddress = await create2Factory.deploy(wethInit, 0)
const testUniswapInit = await new TestUniswap__factory(ethersSigner).getDeployTransaction(wethAddress)
const testUniswapAddress = await create2Factory.deploy(testUniswapInit, 0)

const tokenPaymasterConfig: TokenPaymaster.TokenPaymasterConfigStruct = {
priceMaxAge: 86400,
refundPostopCost: 40000,
minEntryPointBalance,
priceMarkup: priceDenominator.mul(15).div(10) // +50%
}

const nativeAssetOracleInit = await new TestOracle2__factory(ethersSigner).getDeployTransaction(initialPriceEther, 8)
const nativeAssetOracleAddress = await create2Factory.deploy(nativeAssetOracleInit, 0, 10_000_000)
const tokenOracleInit = await new TestOracle2__factory(ethersSigner).getDeployTransaction(initialPriceToken, 8)
const tokenOracleAddress = await create2Factory.deploy(tokenOracleInit, 0, 10_000_000)

const oracleHelperConfig: OracleHelperNamespace.OracleHelperConfigStruct = {
cacheTimeToLive: 100000000,
maxOracleRoundAge: 0,
nativeOracle: nativeAssetOracleAddress,
nativeOracleReverse: false,
priceUpdateThreshold: priceDenominator.mul(2).div(10), // +20%
tokenOracle: tokenOracleAddress,
tokenOracleReverse: false,
tokenToNativeOracle: false
}

const uniswapHelperConfig: UniswapHelperNamespace.UniswapHelperConfigStruct = {
minSwapAmount: 1,
slippage: 5,
uniswapPoolFee: 3
}

const owner = await ethersSigner.getAddress()

const paymasterInit = hexValue(new TokenPaymaster__factory(ethersSigner).getDeployTransaction(
tokenAddress,
g.entryPoint().address,
wethAddress,
testUniswapAddress,
tokenPaymasterConfig,
oracleHelperConfig,
uniswapHelperConfig,
owner
).data!)
paymasterAddress = await create2Factory.deploy(paymasterInit, 0)
const paymaster = TokenPaymaster__factory.connect(paymasterAddress, ethersSigner)
await paymaster.addStake(1, { value: 1 })
await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') })
await paymaster.updateCachedPrice(true)
await g.createAccounts1(11)
await token.sudoMint(await ethersSigner.getAddress(), parseEther('20'))
await token.transfer(paymaster.address, parseEther('0.1'))
for (const address of g.createdAccounts) {
await token.transfer(address, parseEther('1'))
await token.sudoApprove(address, paymaster.address, ethers.constants.MaxUint256)
}

console.log('==addresses:', {
ethersSigner: await ethersSigner.getAddress(),
paymasterAddress,
nativeAssetOracleAddress,
tokenOracleAddress,
tokenAddress,
owner,
createdAccounts: g.createdAccounts
})
})

it('token paymaster', async function () {
await g.addTestRow({ title: 'token paymaster', count: 1, paymaster: paymasterAddress, diffLastGas: false })
await g.addTestRow({
title: 'token paymaster with diff',
count: 2,
paymaster: paymasterAddress,
diffLastGas: true
})
})

it('token paymaster 10', async function () {
if (g.skipLong()) this.skip()

await g.addTestRow({ title: 'token paymaster', count: 10, paymaster: paymasterAddress, diffLastGas: false })
await g.addTestRow({
title: 'token paymaster with diff',
count: 11,
paymaster: paymasterAddress,
diffLastGas: true
})
})
})
45 changes: 38 additions & 7 deletions gascalc/GasChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ export class GasChecker {
defaultAbiCoder.encode(['address'], [this.entryPoint().address])
]), 0, 2885201)
console.log('factaddr', factoryAddress)
GasCheckCollector.inst.setContractName(factoryAddress, 'SimpleAccountFactory')
const fact = SimpleAccountFactory__factory.connect(factoryAddress, ethersSigner)

const implAddress = await fact.accountImplementation()
GasCheckCollector.inst.setContractName(implAddress, 'SimpleAccount')
// create accounts
const creationOps: UserOperation[] = []
for (const n of range(count)) {
Expand Down Expand Up @@ -157,6 +161,7 @@ export class GasChecker {
this.accounts[addr] = this.accountOwner
// deploy if not already deployed.
await fact.createAccount(this.accountOwner.address, salt)
GasCheckCollector.inst.setContractName(addr, 'ERC1967Proxy')
const accountBalance = await GasCheckCollector.inst.entryPoint.balanceOf(addr)
if (accountBalance.lte(minDepositOrBalance)) {
await GasCheckCollector.inst.entryPoint.depositTo(addr, { value: minDepositOrBalance.mul(5) })
Expand Down Expand Up @@ -207,6 +212,7 @@ export class GasChecker {
dest = account
} else if (dest === 'random') {
dest = createAddress()
GasCheckCollector.inst.setContractName(dest, '!EOA!')
const destBalance = await getBalance(dest)
if (destBalance.eq(0)) {
console.log('dest replenish', dest)
Expand Down Expand Up @@ -265,8 +271,8 @@ export class GasChecker {
count: info.count,
gasUsed,
accountEst,
title: info.title
// receipt: rcpt
title: info.title,
receipt: rcpt
}
if (info.diffLastGas) {
ret1.gasDiff = gasDiff
Expand Down Expand Up @@ -294,6 +300,13 @@ export class GasCheckCollector {
static initPromise?: Promise<GasCheckCollector>

entryPoint: EntryPoint
createJsonResult: boolean = false
readonly contracts = new Map<string, string>()
readonly txHashes: string[] = []

setContractName (address: string, name: string): void {
this.contracts.set(address.toLowerCase(), name)
}

static async init (): Promise<void> {
if (this.inst == null) {
Expand All @@ -307,6 +320,7 @@ export class GasCheckCollector {
async _init (entryPointAddressOrTest: string = 'test'): Promise<this> {
console.log('signer=', await ethersSigner.getAddress())
DefaultGasTestInfo.beneficiary = createAddress()
this.setContractName(DefaultGasTestInfo.beneficiary, '!EOA! (beneficiary)')

const bal = await getBalance(ethersSigner.getAddress())
if (bal.gt(parseEther('100000000'))) {
Expand All @@ -321,14 +335,16 @@ export class GasCheckCollector {
} else {
this.entryPoint = EntryPoint__factory.connect(entryPointAddressOrTest, ethersSigner)
}
this.setContractName(this.entryPoint.address, 'EntryPoint')

const tableHeaders = [
'handleOps description ',
'count',
'total gasUsed',
'per UserOp gas\n(delta for\none UserOp)',
// 'per UserOp gas\n(delta for\none UserOp)',
// 'account.exec()\nestimateGas',
'per UserOp overhead\n(compared to\naccount.exec())'
// 'per UserOp overhead\n(compared to\naccount.exec())',
'transaction hash'
]

this.initTable(tableHeaders)
Expand Down Expand Up @@ -380,7 +396,19 @@ export class GasCheckCollector {

const tableOutput = table(this.tabRows, this.tableConfig)
write(tableOutput)
process.exit(0)
if (this.createJsonResult) {
this.writeResultInJson()
}
// process.exit(0)
}

writeResultInJson (): void {
const res = {
contracts: Object.fromEntries(this.contracts.entries()),
transactions: this.txHashes
}

fs.writeFileSync(`gas-checker-result-${Date.now()}.json`, JSON.stringify(res))
}

addRow (res: GasTestResult): void {
Expand All @@ -391,9 +419,12 @@ export class GasCheckCollector {
res.title,
res.count,
gasUsed,
res.gasDiff ?? '',
// res.gasDiff ?? '',
// res.accountEst,
perOp])
// perOp,
res.receipt?.transactionHash])

this.txHashes.push(res.receipt!.transactionHash)
}
}

Expand Down

0 comments on commit 95e7af9

Please sign in to comment.