Skip to content

Commit

Permalink
Fix runOp Script
Browse files Browse the repository at this point in the history
I was running the 4337 `runOp.ts` script this morning and noticed it was
subtly broken. This PR fixes it.
  • Loading branch information
nlordell committed Jun 6, 2024
1 parent 4b7b71a commit 9b00830
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 17 deletions.
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
33 changes: 20 additions & 13 deletions modules/4337/src/utils/safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ 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 +86,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 +114,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 +160,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 @@ -174,35 +175,41 @@ export class Safe4337Operation {
action: MetaTransaction,
globalConfig: GlobalConfig,
): Promise<Safe4337Operation> {
const initCode = (await safe.isDeployed()) ? '0x' : safe.getInitCode()
const initCode = (await safe.isDeployed()) ? "0x" : safe.getInitCode();
const nonce = (await callInterface(provider, globalConfig.entryPoint, 'getNonce', [safe.address, 0]))[0]
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

0 comments on commit 9b00830

Please sign in to comment.