Skip to content

Commit

Permalink
TokenPaymaster "gas-calc" test (eth-infinitism#300)
Browse files Browse the repository at this point in the history
* Initial commit for TokenPaymaster "gas-calc" test
* Deploy all TokenPaymaster contracts with Create2Factory for "gas-calc"
* Make TestPaymaster use postOp
* Storage-Optimization for TokenPaymaster
   - change gas and timestamps to 48 bits
   - change blanaces and multipliers to 128 bit
   - saves 10kgas (and since 10-op batch uses the same TokenPaymaster, the
* add initial balance to paymaster
  • Loading branch information
forshtat authored and drortirosh committed Jan 7, 2024
1 parent 4063d81 commit f6a7434
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 9 deletions.
11 changes: 10 additions & 1 deletion contracts/test/TestPaymasterAcceptAll.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.12;

import "../core/BasePaymaster.sol";
/* solhint-disable no-empty-blocks */

/**
* test paymaster, that pays for everything, without any check.
Expand All @@ -21,6 +22,14 @@ contract TestPaymasterAcceptAll is BasePaymaster {
internal virtual override view
returns (bytes memory context, uint256 validationData) {
(userOp, userOpHash, maxCost);
return ("", 0);
// return a context, as it is used for EntryPoint gas checking.
return ("1", 0);
}

function _postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost
) internal override {
}
}
132 changes: 132 additions & 0 deletions gascalc/4-token-paymaster.gas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
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('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: 0,
nativeOracle: nativeAssetOracleAddress,
nativeOracleReverse: false,
priceUpdateThreshold: 200_000, // +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
})
})
})
24 changes: 16 additions & 8 deletions reports/gas-checker.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,36 @@
║ │ │ │ (delta for │ (compared to ║
║ │ │ │ one UserOp) │ account.exec()) ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple │ 1 │ 81930 │ │ ║
║ simple │ 1 │ 81918 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple - diff from previous │ 2 │ │ 44187 │ 15173 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple │ 10 │ 479742 │ │ ║
║ simple │ 10 │ 479730 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple - diff from previous │ 11 │ │ 44247 │ 15233 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster │ 1 │ 88187 │ │ ║
║ simple paymaster │ 1 │ 89813 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster with diff │ 2 │ │ 4311414100
║ simple paymaster with diff │ 2 │ │ 4479615782
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster │ 10 │ 476706 │ │ ║
║ simple paymaster │ 10 │ 493254 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster with diff │ 11 │ │ 4317314159
║ simple paymaster with diff │ 11 │ │ 4482015806
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx 5k │ 1 │ 182987 │ │ ║
║ big tx 5k │ 1 │ 182975 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx - diff from previous │ 2 │ │ 144698 │ 19438 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx 5k │ 10 │ 1485386 │ │ ║
║ big tx 5k │ 10 │ 1485374 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx - diff from previous │ 11 │ │ 144759 │ 19499 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ token paymaster │ 1 │ 148244 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ token paymaster with diff │ 2 │ │ 72920 │ 43906 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ token paymaster │ 10 │ 804795 │ │ ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ token paymaster with diff │ 11 │ │ 73015 │ 44001 ║
╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝

0 comments on commit f6a7434

Please sign in to comment.