Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix runOp Script #435

Merged
merged 1 commit into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions modules/4337/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
"deploy": "hardhat deploy --network",
"lint": "pnpm run lint:sol && npm run lint:ts",
"lint:sol": "solhint 'contracts/**/*.sol'",
"lint:ts": "eslint ./src --fix && eslint ./test --fix",
"fmt": "prettier --write ./contracts/**/*.sol",
"lint:ts": "eslint ./src && eslint ./test",
"lint:fix": "eslint ./src --fix && eslint ./test --fix",
"fmt": "prettier --write .",
"fmt:check": "prettier --check ./**/*.sol",
"prepare": "pnpm run build"
},
Expand Down
15 changes: 11 additions & 4 deletions modules/4337/scripts/runOp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,18 @@ const runOp = async () => {
// All other methods return an error
const accountAbstractionProvider = new MultiProvider4337(BUNDLER_URL!, ethers.provider)
const entryPoints = await getSupportedEntryPoints(accountAbstractionProvider)
const entryPoint = entryPoints[0]
const moduleAddress = MODULE_ADDRESS ?? (await getSafe4337Module().then((module) => module.getAddress()))
const moduleSupportedEntrypoint = await user1.call({ to: moduleAddress, data: INTERFACES.encodeFunctionData('SUPPORTED_ENTRYPOINT') })
const [moduleSupportedEntrypoint] = ethers.AbiCoder.defaultAbiCoder().decode(
['address'],
await user1.call({ to: moduleAddress, data: INTERFACES.encodeFunctionData('SUPPORTED_ENTRYPOINT') }),
)
console.log({ moduleAddress, moduleSupportedEntrypoint })

const entryPoint = entryPoints.find((entry) => entry === moduleSupportedEntrypoint)
if (entryPoint === undefined) {
throw new Error('Module does not support any of the available entry points')
}

const proxyCreationCode = (await callInterface(PROXY_FACTORY_ADDRESS, 'proxyCreationCode'))[0]

const globalConfig: GlobalConfig = {
Expand All @@ -68,10 +75,10 @@ const runOp = async () => {

safe.connect(accountAbstractionProvider)

console.log(safe.address)
console.log({ safe: safe.address })
const safeBalance = await ethers.provider.getBalance(safe.address)
const minBalance = ethers.parseEther('0.01')
console.log(safeBalance)
console.log({ safeBalance })
if (safeBalance < minBalance) {
await (await user1.sendTransaction({ to: safe.address, value: ethers.parseEther('0.01') })).wait()
}
Expand Down
38 changes: 26 additions & 12 deletions modules/4337/src/utils/safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import { Provider, Signer, ethers } from 'ethers'

// Import from Safe contracts repo once it is upgraded to ethers v6 and can be installed via npm
import { MetaTransaction, SafeSignature, SignedSafeTransaction, buildSignatureBytes } from './execution'
import { PackedUserOperation, UserOperation, EIP712_SAFE_OPERATION_TYPE, packGasParameters, unpackUserOperation } from './userOp'
import {
PackedUserOperation,
UserOperation,
EIP712_SAFE_OPERATION_TYPE,
packGasParameters,
unpackUserOperation,
unpackInitCode,
} from './userOp'

export { MultiProvider4337 }

Expand Down Expand Up @@ -86,7 +93,6 @@ const callInterface = async (provider: Provider, contract: string, method: strin
to: contract,
data: INTERFACES.encodeFunctionData(method, params),
})
console.log(result)
return INTERFACES.decodeFunctionResult(method, result)
}

Expand Down Expand Up @@ -115,6 +121,7 @@ export class Safe4337Operation {
{
safe: this.safe.address,
callData: actionCalldata(this.action),
paymasterAndData: '0x',
entryPoint: this.globalConfig.entryPoint,
...this.params,
},
Expand Down Expand Up @@ -160,12 +167,13 @@ export class Safe4337Operation {
{
safe: this.safe.address,
callData: actionCalldata(this.action),
paymasterAndData: '0x',
entryPoint: this.globalConfig.entryPoint,
...this.params,
},
),
})
console.log(this.signatures)
console.log({ signatures: this.signatures })
}

static async build(
Expand All @@ -179,30 +187,36 @@ export class Safe4337Operation {
const estimateOperation = {
sender: safe.address,
callData: actionCalldata(action),
paymasterAndData: '0x',
nonce: ethers.toBeHex(nonce),
initCode,
signature: '0x'.padEnd(130, 'a'),
...unpackInitCode({ initCode }),
// For some providers we need to set some really high values to allow estimation
preVerificationGas: ethers.toBeHex(1000000),
verificationGasLimit: ethers.toBeHex(1000000),
callGasLimit: ethers.toBeHex(10000000),
// To keep the required funds low, the gas fee is set close to the minimum
verificationGasLimit: ethers.toBeHex(1000000),
preVerificationGas: ethers.toBeHex(1000000),
// User arbitrary gas fee values - note that we use lower values in order to reduce the amount
// of gas fees used in tests; when estimating with a real bundler, they will choose these for
// for us anyway.
maxFeePerGas: '0x10',
maxPriorityFeePerGas: '0x10',
// Use dummy signature that makes ECRECOVER get called in order to have slightly more accurate
// estimates for single signer operations.
signature: `0x${'aa'.repeat(32)}${'bb'.repeat(32)}1b`,
}
const estimates = await provider.send('eth_estimateUserOperationGas', [
{
...estimateOperation,
},
globalConfig.entryPoint,
])
console.log(estimates)

const feeData = await provider.getFeeData()
console.log({ estimates })

const feeData = { ...(await provider.getFeeData()) }
if (!feeData.maxFeePerGas || !feeData.maxPriorityFeePerGas) throw Error('Missing fee data')

// Some bundlers require higher priority fees and use non-standard APIs for this. Instead, just
// bump the priority fee by 20% to ensure that the operation is accepted by the bundler.
feeData.maxPriorityFeePerGas += (feeData.maxPriorityFeePerGas * 20n) / 100n

const params: OperationParams = {
nonce,
initCode,
Expand Down
Loading