mirror of
https://github.com/getwax/wax.git
synced 2026-01-09 23:27:58 -05:00
Merge pull request #1 from getwax/anon-aadhaar
Use correct verfier for AnonAadhaar
This commit is contained in:
@@ -17,16 +17,18 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@account-abstraction/contracts": "0.7.0",
|
"@account-abstraction/contracts": "0.7.0",
|
||||||
"@account-abstraction/utils": "^0.6.0",
|
"@account-abstraction/utils": "^0.6.0",
|
||||||
"@anon-aadhaar/contracts": "2.2.0",
|
|
||||||
"@anon-aadhaar/core": "2.2.0",
|
"@anon-aadhaar/core": "2.2.0",
|
||||||
"@nomicfoundation/hardhat-chai-matchers": "^2.0.0",
|
"@nomicfoundation/hardhat-chai-matchers": "^2.0.0",
|
||||||
"@nomicfoundation/hardhat-ethers": "^3.0.0",
|
"@nomicfoundation/hardhat-ethers": "^3.0.0",
|
||||||
|
"@nomicfoundation/hardhat-ignition": "^0.15.5",
|
||||||
|
"@nomicfoundation/hardhat-ignition-ethers": "^0.15.0",
|
||||||
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
|
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
|
||||||
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
|
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
|
||||||
"@nomicfoundation/hardhat-verify": "^1.0.0",
|
"@nomicfoundation/hardhat-verify": "^2.0.8",
|
||||||
|
"@nomicfoundation/ignition-core": "^0.15.5",
|
||||||
"@thehubbleproject/bls": "^0.5.1",
|
"@thehubbleproject/bls": "^0.5.1",
|
||||||
"@typechain/ethers-v6": "^0.4.0",
|
"@typechain/ethers-v6": "^0.5.1",
|
||||||
"@typechain/hardhat": "^8.0.0",
|
"@typechain/hardhat": "^9.1.0",
|
||||||
"@types/chai": "^4.2.0",
|
"@types/chai": "^4.2.0",
|
||||||
"@types/circomlibjs": "^0.1.6",
|
"@types/circomlibjs": "^0.1.6",
|
||||||
"@types/mocha": ">=9.1.0",
|
"@types/mocha": ">=9.1.0",
|
||||||
@@ -44,8 +46,8 @@
|
|||||||
"eslint-plugin-import": "^2.28.1",
|
"eslint-plugin-import": "^2.28.1",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
"ethers": "^6.4.0",
|
"ethers": "^6.4.0",
|
||||||
"hardhat": "^2.17.1",
|
"hardhat": "^2.22.6",
|
||||||
"hardhat-gas-reporter": "^1.0.8",
|
"hardhat-gas-reporter": "^2.2.0",
|
||||||
"hardhat-preprocessor": "^0.1.5",
|
"hardhat-preprocessor": "^0.1.5",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"solidity-coverage": "^0.8.0",
|
"solidity-coverage": "^0.8.0",
|
||||||
@@ -53,4 +55,4 @@
|
|||||||
"typechain": "^8.1.0",
|
"typechain": "^8.1.0",
|
||||||
"typescript": "^5.4.3"
|
"typescript": "^5.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/plugins/src/paymaster/README.md
Normal file
3
packages/plugins/src/paymaster/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Paymaster
|
||||||
|
|
||||||
|
These are exemplary paymaster contracts. The SponsorEverythingPaymaster contract and its test can serve as references when developing more complex paymasters for your specific use cases.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity >=0.8.4 <0.9.0;
|
||||||
|
|
||||||
|
import {IEntryPoint} from 'account-abstraction/interfaces/IEntryPoint.sol';
|
||||||
|
|
||||||
|
import {BasePaymaster} from 'account-abstraction/core/BasePaymaster.sol';
|
||||||
|
import {UserOperationLib} from 'account-abstraction/core/UserOperationLib.sol';
|
||||||
|
import {PackedUserOperation} from 'account-abstraction/interfaces/PackedUserOperation.sol';
|
||||||
|
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
THIS CONTRACT IS STILL IN ACTIVE DEVELOPMENT. NOT FOR PRODUCTION USE
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
/// @title This paymaster sponsors everything.
|
||||||
|
contract SponsorEverythingPaymaster is BasePaymaster {
|
||||||
|
using UserOperationLib for PackedUserOperation;
|
||||||
|
|
||||||
|
constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a user operation.
|
||||||
|
* @param userOp - The user operation.
|
||||||
|
* @param userOpHash - The hash of the user operation.
|
||||||
|
* @param maxCost - The maximum cost of the user operation.
|
||||||
|
*/
|
||||||
|
function _validatePaymasterUserOp(
|
||||||
|
PackedUserOperation calldata userOp,
|
||||||
|
bytes32 userOpHash,
|
||||||
|
uint256 maxCost
|
||||||
|
) internal virtual override returns (bytes memory context, uint256 validationData) {
|
||||||
|
// Validation logic comes here.
|
||||||
|
// Approve everything.
|
||||||
|
return ("", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ pragma abicoder v2;
|
|||||||
|
|
||||||
import {Safe4337Base, SIG_VALIDATION_FAILED} from "./utils/Safe4337Base.sol";
|
import {Safe4337Base, SIG_VALIDATION_FAILED} from "./utils/Safe4337Base.sol";
|
||||||
import {IEntryPoint, PackedUserOperation} from "account-abstraction/interfaces/IEntryPoint.sol";
|
import {IEntryPoint, PackedUserOperation} from "account-abstraction/interfaces/IEntryPoint.sol";
|
||||||
import {IAnonAadhaar} from "@anon-aadhaar/contracts/interfaces/IAnonAadhaar.sol";
|
import {IAnonAadhaar} from "./utils/anonAadhaar/interfaces/IAnonAadhaar.sol";
|
||||||
|
|
||||||
interface ISafe {
|
interface ISafe {
|
||||||
function enableModule(address module) external;
|
function enableModule(address module) external;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//SPDX-License-Identifier: Unlicense
|
//SPDX-License-Identifier: Unlicense
|
||||||
pragma solidity ^0.8.19;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "@anon-aadhaar/contracts/interfaces/IAnonAadhaarGroth16Verifier.sol";
|
import "./interfaces/IAnonAadhaarGroth16Verifier.sol";
|
||||||
import "@anon-aadhaar/contracts/interfaces/IAnonAadhaar.sol";
|
import "./interfaces/IAnonAadhaar.sol";
|
||||||
|
|
||||||
// Note: This is a AnonAadhaar contract with a modification that made`verifier` state variable immutable
|
// Note: This is a AnonAadhaar contract with a modification that made`verifier` state variable immutable
|
||||||
// so that verification doesn't fail due to invalid storage access.
|
// so that verification doesn't fail due to invalid storage access.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
pragma solidity >=0.7.0 <0.9.0;
|
pragma solidity >=0.7.0 <0.9.0;
|
||||||
|
|
||||||
contract Verifier {
|
contract AnonAadhaarVerifier {
|
||||||
// Scalar field size
|
// Scalar field size
|
||||||
uint256 constant r =
|
uint256 constant r =
|
||||||
21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||||
5
packages/plugins/src/safe/utils/anonAadhaar/README.md
Normal file
5
packages/plugins/src/safe/utils/anonAadhaar/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Anon Aadhaar Contracts
|
||||||
|
|
||||||
|
These contracts are copied from https://github.com/anon-aadhaar/anon-aadhaar/tree/main/packages/contracts @ `v2.2.0`. This has been done for 2 reasons:
|
||||||
|
- `AnonAadhaarVerifier.sol` needed to be modified to use gas opcodes that work within the [validation cycle gas opcode limitations for ERC-4337 (OP-012)](https://eips.ethereum.org/EIPS/eip-7562#opcode-rules).
|
||||||
|
- Using the `@anon-aadhaar/contracts` npm package's contract interfaces causes issues with Typechain generation in this project.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
|
interface IAnonAadhaar {
|
||||||
|
function verifyAnonAadhaarProof(
|
||||||
|
uint nullifierSeed,
|
||||||
|
uint nullifier,
|
||||||
|
uint timestamp,
|
||||||
|
uint signal,
|
||||||
|
uint[4] memory revealArray,
|
||||||
|
uint[8] memory groth16Proof
|
||||||
|
) external view returns (bool);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
|
interface IAnonAadhaarGroth16Verifier {
|
||||||
|
function verifyProof(
|
||||||
|
uint[2] calldata _pA,
|
||||||
|
uint[2][2] calldata _pB,
|
||||||
|
uint[2] calldata _pC,
|
||||||
|
uint[9] calldata publicInputs
|
||||||
|
) external view returns (bool);
|
||||||
|
}
|
||||||
@@ -17,3 +17,8 @@ import {Safe} from "safe-contracts/contracts/Safe.sol";
|
|||||||
import {EntryPoint} from "account-abstraction/core/EntryPoint.sol";
|
import {EntryPoint} from "account-abstraction/core/EntryPoint.sol";
|
||||||
import {SimpleAccountFactory} from "account-abstraction/samples/SimpleAccountFactory.sol";
|
import {SimpleAccountFactory} from "account-abstraction/samples/SimpleAccountFactory.sol";
|
||||||
import {BLSSignatureAggregator} from "account-abstraction/samples/bls/BLSSignatureAggregator.sol";
|
import {BLSSignatureAggregator} from "account-abstraction/samples/bls/BLSSignatureAggregator.sol";
|
||||||
|
|
||||||
|
// Anon-Aadhaar
|
||||||
|
import {AnonAadhaar} from "./anonAadhaar/AnonAadhaar.sol";
|
||||||
|
import {AnonAadhaarVerifier} from "./anonAadhaar/AnonAadhaarVerifier.sol";
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import DeterministicDeployer from "../../lib-ts/deterministic-deployer/Determini
|
|||||||
import {
|
import {
|
||||||
SafeAnonAadhaarFactory__factory,
|
SafeAnonAadhaarFactory__factory,
|
||||||
SafeAnonAadhaarPlugin__factory,
|
SafeAnonAadhaarPlugin__factory,
|
||||||
Verifier__factory,
|
AnonAadhaarVerifier__factory,
|
||||||
AnonAadhaar__factory,
|
AnonAadhaar__factory,
|
||||||
Safe,
|
Safe,
|
||||||
AnonAadhaar,
|
AnonAadhaar,
|
||||||
@@ -74,13 +74,15 @@ describe("SafeAnonAadhaarPlugin", () => {
|
|||||||
const signer = await provider.getSigner();
|
const signer = await provider.getSigner();
|
||||||
|
|
||||||
// Deploy AnonAadhaarGroth16Verifier contract
|
// Deploy AnonAadhaarGroth16Verifier contract
|
||||||
const anonAadhaarVerifier = await new Verifier__factory(signer).deploy();
|
const anonAadhaarVerifier = await new AnonAadhaarVerifier__factory(signer).deploy();
|
||||||
|
await anonAadhaarVerifier.waitForDeployment();
|
||||||
|
|
||||||
// Deploy AnonAadhaar contract
|
// Deploy AnonAadhaar contract
|
||||||
anonAadhaar = await new AnonAadhaar__factory(signer).deploy(
|
anonAadhaar = await new AnonAadhaar__factory(signer).deploy(
|
||||||
await anonAadhaarVerifier.getAddress(),
|
await anonAadhaarVerifier.getAddress(),
|
||||||
BigInt(testPublicKeyHash).toString()
|
BigInt(testPublicKeyHash).toString(),
|
||||||
);
|
);
|
||||||
|
await anonAadhaar.waitForDeployment();
|
||||||
|
|
||||||
anonAadhaarAddress = await anonAadhaar.getAddress();
|
anonAadhaarAddress = await anonAadhaar.getAddress();
|
||||||
|
|
||||||
@@ -173,12 +175,17 @@ describe("SafeAnonAadhaarPlugin", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// proving
|
// proving
|
||||||
|
console.debug("Generating Anon Aadhaar proof. This could take some time...");
|
||||||
|
const proofTimingKey = "Anon Aadhaar proof generation time";
|
||||||
|
console.time(proofTimingKey);
|
||||||
const anonAadhaarCore = await prove(args);
|
const anonAadhaarCore = await prove(args);
|
||||||
|
console.timeEnd(proofTimingKey);
|
||||||
|
|
||||||
const anonAadhaarProof = anonAadhaarCore.proof;
|
const anonAadhaarProof = anonAadhaarCore.proof;
|
||||||
const packedGroth16Proof = packGroth16Proof(anonAadhaarProof.groth16Proof);
|
const packedGroth16Proof = packGroth16Proof(anonAadhaarProof.groth16Proof);
|
||||||
|
|
||||||
// view call to AnonAadhaar contract to see if verification returns true
|
// view call to AnonAadhaar contract to see if verification returns true
|
||||||
const ret = await anonAadhaar.verifyAnonAadhaarProof(
|
expect(await anonAadhaar.verifyAnonAadhaarProof(
|
||||||
nullifierSeed,
|
nullifierSeed,
|
||||||
anonAadhaarProof.nullifier,
|
anonAadhaarProof.nullifier,
|
||||||
anonAadhaarProof.timestamp,
|
anonAadhaarProof.timestamp,
|
||||||
@@ -190,8 +197,7 @@ describe("SafeAnonAadhaarPlugin", () => {
|
|||||||
anonAadhaarProof.state,
|
anonAadhaarProof.state,
|
||||||
],
|
],
|
||||||
packedGroth16Proof
|
packedGroth16Proof
|
||||||
);
|
)).to.equal(true);
|
||||||
console.log("ret: ", ret);
|
|
||||||
|
|
||||||
// encode proof data into userOpSignature
|
// encode proof data into userOpSignature
|
||||||
const encoder = ethers.AbiCoder.defaultAbiCoder();
|
const encoder = ethers.AbiCoder.defaultAbiCoder();
|
||||||
@@ -199,7 +205,7 @@ describe("SafeAnonAadhaarPlugin", () => {
|
|||||||
["uint", "uint", "uint", "uint[4]", "uint[8]"],
|
["uint", "uint", "uint", "uint[4]", "uint[8]"],
|
||||||
[
|
[
|
||||||
BigInt(nullifierSeed),
|
BigInt(nullifierSeed),
|
||||||
Number(anonAadhaarCore?.proof.timestamp),
|
Number(anonAadhaarProof.timestamp),
|
||||||
BigInt(userOpHash), // insert userOpHash into signature
|
BigInt(userOpHash), // insert userOpHash into signature
|
||||||
[
|
[
|
||||||
anonAadhaarProof.ageAbove18,
|
anonAadhaarProof.ageAbove18,
|
||||||
|
|||||||
110
packages/plugins/test/e2e/SafeSponsorEverythingPaymaster.test.ts
Normal file
110
packages/plugins/test/e2e/SafeSponsorEverythingPaymaster.test.ts
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { expect } from "chai";
|
||||||
|
import { ethers } from "ethers";
|
||||||
|
import {
|
||||||
|
SafeECDSAFactory__factory,
|
||||||
|
SafeECDSAPlugin__factory,
|
||||||
|
SponsorEverythingPaymaster__factory,
|
||||||
|
EntryPoint__factory
|
||||||
|
} from "../../typechain-types";
|
||||||
|
import receiptOf from "./utils/receiptOf";
|
||||||
|
import { setupTests } from "./utils/setupTests";
|
||||||
|
import { createAndSendUserOpWithEcdsaSig } from "./utils/createUserOp";
|
||||||
|
|
||||||
|
const oneEther = ethers.parseEther("1");
|
||||||
|
|
||||||
|
describe("SafeSponsorEverythingPaymasterPlugin", () => {
|
||||||
|
it("should pass the ERC4337 validation", async () => {
|
||||||
|
const {
|
||||||
|
bundlerProvider,
|
||||||
|
provider,
|
||||||
|
admin,
|
||||||
|
owner,
|
||||||
|
entryPointAddress,
|
||||||
|
deployer,
|
||||||
|
safeSingleton,
|
||||||
|
} = await setupTests();
|
||||||
|
|
||||||
|
// Deploy paymaster.
|
||||||
|
const paymaster = await new SponsorEverythingPaymaster__factory(admin).deploy(entryPointAddress);
|
||||||
|
await paymaster.waitForDeployment();
|
||||||
|
const paymasterAddress = await paymaster.getAddress();
|
||||||
|
|
||||||
|
// Paymaster deposits.
|
||||||
|
await paymaster.connect(admin).deposit({ value: oneEther })
|
||||||
|
|
||||||
|
const recipient = ethers.Wallet.createRandom();
|
||||||
|
const transferAmount = oneEther;
|
||||||
|
const dummySignature = await owner.signMessage("dummy sig");
|
||||||
|
|
||||||
|
// Deploy ecdsa plugin
|
||||||
|
const safeECDSAFactory = await deployer.connectOrDeploy(
|
||||||
|
SafeECDSAFactory__factory,
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const createArgs = [
|
||||||
|
safeSingleton,
|
||||||
|
entryPointAddress,
|
||||||
|
await owner.getAddress(),
|
||||||
|
0,
|
||||||
|
] satisfies Parameters<typeof safeECDSAFactory.create.staticCall>;
|
||||||
|
|
||||||
|
const accountAddress = await safeECDSAFactory.create.staticCall(
|
||||||
|
...createArgs,
|
||||||
|
);
|
||||||
|
|
||||||
|
await receiptOf(safeECDSAFactory.create(...createArgs));
|
||||||
|
|
||||||
|
const safeEcdsaPlugin = SafeECDSAPlugin__factory.connect(
|
||||||
|
accountAddress,
|
||||||
|
owner,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Native tokens for the pre-fund
|
||||||
|
await receiptOf(
|
||||||
|
admin.sendTransaction({
|
||||||
|
to: accountAddress,
|
||||||
|
value: oneEther,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Construct userOp
|
||||||
|
const userOpCallData = safeEcdsaPlugin.interface.encodeFunctionData(
|
||||||
|
"execTransaction",
|
||||||
|
[recipient.address, transferAmount, "0x00"],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Note: factoryParams is not used because we need to create both the safe
|
||||||
|
// proxy and the plugin, and 4337 currently only allows one contract
|
||||||
|
// creation in this step. Since we need an extra step anyway, it's simpler
|
||||||
|
// to do the whole create outside of 4337.
|
||||||
|
const factoryParams = {
|
||||||
|
factory: "0x",
|
||||||
|
factoryData: "0x",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check paymaster balances before and after sending UserOp.
|
||||||
|
const entrypoint = EntryPoint__factory.connect(entryPointAddress, provider)
|
||||||
|
const paymasterBalanceBefore = await entrypoint.balanceOf(paymasterAddress)
|
||||||
|
|
||||||
|
// Send userOp
|
||||||
|
await createAndSendUserOpWithEcdsaSig(
|
||||||
|
provider,
|
||||||
|
bundlerProvider,
|
||||||
|
owner,
|
||||||
|
accountAddress,
|
||||||
|
factoryParams,
|
||||||
|
userOpCallData,
|
||||||
|
entryPointAddress,
|
||||||
|
dummySignature,
|
||||||
|
paymasterAddress,
|
||||||
|
3e5,
|
||||||
|
"0x"
|
||||||
|
);
|
||||||
|
|
||||||
|
const paymasterBalanceAfter = await entrypoint.balanceOf(paymasterAddress)
|
||||||
|
|
||||||
|
expect(paymasterBalanceBefore).greaterThan(paymasterBalanceAfter)
|
||||||
|
expect(await provider.getBalance(recipient.address)).to.equal(oneEther);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable prettier/prettier */
|
/* eslint-disable prettier/prettier */
|
||||||
/* eslint-disable @typescript-eslint/comma-dangle */
|
/* eslint-disable @typescript-eslint/comma-dangle */
|
||||||
import { ethers, getBytes, NonceManager, Signer } from "ethers";
|
import { BigNumberish, BytesLike, ethers, getBytes, NonceManager, Signer } from "ethers";
|
||||||
import { AddressZero } from "@ethersproject/constants";
|
import { AddressZero } from "@ethersproject/constants";
|
||||||
|
|
||||||
import { SafeProxyFactory } from "../../../typechain-types/lib/safe-contracts/contracts/proxies/SafeProxyFactory";
|
import { SafeProxyFactory } from "../../../typechain-types/lib/safe-contracts/contracts/proxies/SafeProxyFactory";
|
||||||
@@ -79,13 +79,16 @@ export const generateFactoryParamsAndAddress = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const createUserOperation = async (
|
export const createUserOperation = async (
|
||||||
provider: ethers.JsonRpcProvider,
|
provider: ethers.JsonRpcProvider,
|
||||||
bundlerProvider: ethers.JsonRpcProvider,
|
bundlerProvider: ethers.JsonRpcProvider,
|
||||||
accountAddress: string,
|
accountAddress: string,
|
||||||
factoryParams: FactoryParams,
|
factoryParams: FactoryParams,
|
||||||
userOpCallData: string,
|
userOpCallData: string,
|
||||||
entryPointAddress: string,
|
entryPointAddress: string,
|
||||||
dummySignature: string
|
dummySignature: string,
|
||||||
|
paymaster?: string,
|
||||||
|
paymasterPostOpGasLimit?: BigNumberish,
|
||||||
|
paymasterData?: BytesLike,
|
||||||
) => {
|
) => {
|
||||||
const entryPoint = EntryPoint__factory.connect(
|
const entryPoint = EntryPoint__factory.connect(
|
||||||
entryPointAddress,
|
entryPointAddress,
|
||||||
@@ -107,55 +110,66 @@ export const createUserOperation = async (
|
|||||||
userOp.factoryData = factoryParams.factoryData;
|
userOp.factoryData = factoryParams.factoryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
callGasLimit,
|
callGasLimit,
|
||||||
verificationGasLimit,
|
verificationGasLimit,
|
||||||
preVerificationGas,
|
preVerificationGas,
|
||||||
maxFeePerGas,
|
paymasterVerificationGasLimit,
|
||||||
maxPriorityFeePerGas,
|
maxFeePerGas,
|
||||||
} = await getGasEstimates(
|
maxPriorityFeePerGas,
|
||||||
provider,
|
} = await getGasEstimates(
|
||||||
bundlerProvider,
|
provider,
|
||||||
userOp,
|
bundlerProvider,
|
||||||
entryPointAddress
|
userOp,
|
||||||
);
|
entryPointAddress,
|
||||||
|
);
|
||||||
|
|
||||||
const unsignedUserOperation = {
|
const unsignedUserOperation = {
|
||||||
sender: accountAddress,
|
sender: accountAddress,
|
||||||
nonce: nonceHex,
|
nonce: nonceHex,
|
||||||
factory: userOp.factory,
|
factory: userOp.factory,
|
||||||
factoryData: userOp.factoryData,
|
factoryData: userOp.factoryData,
|
||||||
callData: userOpCallData,
|
callData: userOpCallData,
|
||||||
callGasLimit,
|
callGasLimit,
|
||||||
verificationGasLimit,
|
verificationGasLimit,
|
||||||
preVerificationGas,
|
preVerificationGas,
|
||||||
maxFeePerGas,
|
maxFeePerGas,
|
||||||
maxPriorityFeePerGas,
|
maxPriorityFeePerGas,
|
||||||
signature: dummySignature,
|
paymaster: paymaster,
|
||||||
} satisfies UserOperation;
|
paymasterVerificationGasLimit: paymaster ? paymasterVerificationGasLimit : undefined,
|
||||||
|
paymasterPostOpGasLimit: paymasterPostOpGasLimit,
|
||||||
|
paymasterData: paymasterData,
|
||||||
|
signature: dummySignature,
|
||||||
|
} satisfies UserOperation;
|
||||||
|
|
||||||
return await ethers.resolveProperties(unsignedUserOperation);
|
return await ethers.resolveProperties(unsignedUserOperation);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createAndSendUserOpWithEcdsaSig = async (
|
export const createAndSendUserOpWithEcdsaSig = async (
|
||||||
provider: ethers.JsonRpcProvider,
|
provider: ethers.JsonRpcProvider,
|
||||||
bundlerProvider: ethers.JsonRpcProvider,
|
bundlerProvider: ethers.JsonRpcProvider,
|
||||||
owner: Signer,
|
owner: Signer,
|
||||||
accountAddress: string,
|
accountAddress: string,
|
||||||
factoryParams: FactoryParams,
|
factoryParams: FactoryParams,
|
||||||
userOpCallData: string,
|
userOpCallData: string,
|
||||||
entryPointAddress: string,
|
entryPointAddress: string,
|
||||||
dummySignature: string
|
dummySignature: string,
|
||||||
|
paymaster?: string,
|
||||||
|
paymasterPostOpGasLimit?: BigNumberish,
|
||||||
|
paymasterData?: BytesLike,
|
||||||
) => {
|
) => {
|
||||||
const unsignedUserOperation = await createUserOperation(
|
const unsignedUserOperation = await createUserOperation(
|
||||||
provider,
|
provider,
|
||||||
bundlerProvider,
|
bundlerProvider,
|
||||||
accountAddress,
|
accountAddress,
|
||||||
factoryParams,
|
factoryParams,
|
||||||
userOpCallData,
|
userOpCallData,
|
||||||
entryPointAddress,
|
entryPointAddress,
|
||||||
dummySignature
|
dummySignature,
|
||||||
);
|
paymaster,
|
||||||
|
paymasterPostOpGasLimit,
|
||||||
|
paymasterData,
|
||||||
|
);
|
||||||
|
|
||||||
const userOpHash = getUserOpHash(
|
const userOpHash = getUserOpHash(
|
||||||
unsignedUserOperation,
|
unsignedUserOperation,
|
||||||
|
|||||||
@@ -9,14 +9,15 @@ export const getGasEstimates = async (
|
|||||||
partialUserOperation: Partial<UserOperation>,
|
partialUserOperation: Partial<UserOperation>,
|
||||||
entryPointAddress: string
|
entryPointAddress: string
|
||||||
) => {
|
) => {
|
||||||
const gasEstimate = (await bundlerProvider.send(
|
const gasEstimate = (await bundlerProvider.send(
|
||||||
"eth_estimateUserOperationGas",
|
"eth_estimateUserOperationGas",
|
||||||
[partialUserOperation, entryPointAddress]
|
[partialUserOperation, entryPointAddress],
|
||||||
)) as {
|
)) as {
|
||||||
verificationGasLimit: string;
|
verificationGasLimit: string;
|
||||||
preVerificationGas: string;
|
preVerificationGas: string;
|
||||||
callGasLimit: string;
|
paymasterVerificationGasLimit: string;
|
||||||
};
|
callGasLimit: string;
|
||||||
|
};
|
||||||
|
|
||||||
const safeVerificationGasLimit =
|
const safeVerificationGasLimit =
|
||||||
BigInt(gasEstimate.verificationGasLimit) +
|
BigInt(gasEstimate.verificationGasLimit) +
|
||||||
@@ -28,13 +29,14 @@ export const getGasEstimates = async (
|
|||||||
|
|
||||||
const { maxFeePerGas, maxPriorityFeePerGas } = await getFeeData(provider);
|
const { maxFeePerGas, maxPriorityFeePerGas } = await getFeeData(provider);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
callGasLimit: gasEstimate.callGasLimit,
|
callGasLimit: gasEstimate.callGasLimit,
|
||||||
verificationGasLimit: ethers.toBeHex(safeVerificationGasLimit),
|
verificationGasLimit: ethers.toBeHex(safeVerificationGasLimit),
|
||||||
preVerificationGas: ethers.toBeHex(safePreVerificationGas),
|
preVerificationGas: ethers.toBeHex(safePreVerificationGas),
|
||||||
maxFeePerGas,
|
paymasterVerificationGasLimit: ethers.toBeHex(safeVerificationGasLimit),
|
||||||
maxPriorityFeePerGas,
|
maxFeePerGas,
|
||||||
};
|
maxPriorityFeePerGas,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getFeeData(provider: ethers.Provider) {
|
export async function getFeeData(provider: ethers.Provider) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user