From 19c45ffab44db1997cf1871bbeb48f1f4bc4c1df Mon Sep 17 00:00:00 2001 From: Sofiia Pidturkina Date: Sat, 13 Jul 2024 14:54:49 +0200 Subject: [PATCH] Delete example, add installing module scripts --- contracts-permissionless-example/abi.js | 22 +++ contracts-permissionless-example/index.js | 51 ------ .../package-lock.json | 168 ------------------ contracts-permissionless-example/package.json | 17 -- contracts/package.json | 3 +- contracts/test/abi.js | 22 +++ contracts/test/add-module-to-account.js | 98 ++++++++++ 7 files changed, 144 insertions(+), 237 deletions(-) create mode 100644 contracts-permissionless-example/abi.js create mode 100644 contracts/test/abi.js create mode 100644 contracts/test/add-module-to-account.js diff --git a/contracts-permissionless-example/abi.js b/contracts-permissionless-example/abi.js new file mode 100644 index 0000000..91d43c0 --- /dev/null +++ b/contracts-permissionless-example/abi.js @@ -0,0 +1,22 @@ +export const abi = [ + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'config', + outputs: [ + { internalType: 'uint48', name: 'lastAccess', type: 'uint48' }, + { internalType: 'uint48', name: 'timeout', type: 'uint48' }, + { internalType: 'address', name: 'nominee', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'smartAccount', type: 'address' }, + ], + name: 'isInitialized', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, +] \ No newline at end of file diff --git a/contracts-permissionless-example/index.js b/contracts-permissionless-example/index.js index 1d9c77b..e69de29 100644 --- a/contracts-permissionless-example/index.js +++ b/contracts-permissionless-example/index.js @@ -1,51 +0,0 @@ -import {generatePrivateKey, privateKeyToAccount} from "viem/accounts"; -import {pimlicoBundlerClient, publicClient, safeAccount, smartAccountClient} from "./smart-account.js"; -import {abi} from "./abi.js"; -import {encodePacked} from "viem"; - -const privateKey = generatePrivateKey() - -const beneficiary = privateKeyToAccount(privateKey); -const timeout = 100; //in seconds - -async function installModule({smartClient, beneficiaryAddress, timeout, moduleType, hook, account, bundlerClient, moduleAddress, publicClient}) { - const isInitialized = (await publicClient.readContract({ - address: moduleAddress, - abi, - functionName: 'isInitialized', - args: [account.address], - })) - - const module = { - module: moduleAddress, - initData: isInitialized - ? '0x' - : encodePacked(['address', 'uint48'], [beneficiaryAddress, timeout]), - deInitData: '0x', - additionalContext: '0x', - type: moduleType, - hook, - } - - - const opHash = await smartClient.installModule({ - type: module.type, - address: module.module, - context: module.initData, - }); - - const receipt = await bundlerClient.waitForUserOperationReceipt({ hash: opHash }) - console.log('receipt', receipt) -} - -installModule({ - smartClient: smartAccountClient, - beneficiaryAddress: beneficiary.address, - timeout, - moduleType: "validator", - hook: '0x', - account: safeAccount, - bundlerClient: pimlicoBundlerClient, - moduleAddress: "0xab614e4a5398bb2a2a0bf73f9c913ec7ff47d81f", //deadmanswitch module address - publicClient -}) diff --git a/contracts-permissionless-example/package-lock.json b/contracts-permissionless-example/package-lock.json index fe01d79..e69de29 100644 --- a/contracts-permissionless-example/package-lock.json +++ b/contracts-permissionless-example/package-lock.json @@ -1,168 +0,0 @@ -{ - "name": "permissionless_test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "permissionless_test", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "permissionless": "^0.1.39", - "viem": "^2.17.3" - } - }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" - }, - "node_modules/@noble/curves": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", - "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/base": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", - "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", - "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/abitype": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz", - "integrity": "sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/isows": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz", - "integrity": "sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/permissionless": { - "version": "0.1.39", - "resolved": "https://registry.npmjs.org/permissionless/-/permissionless-0.1.39.tgz", - "integrity": "sha512-xfJAgzyELvWFqQdm6SxmnjdL6lytUPem3aYhKqHa3jmWHDtE1liXmEVxRYTSjL51xfX0HiZ3ulXH5hIC9r4tEQ==", - "peerDependencies": { - "viem": "^2.14.1" - } - }, - "node_modules/viem": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.17.3.tgz", - "integrity": "sha512-FY/1uBQWfko4Esy8mU1RamvL64TLy91LZwFyQJ20E6AI3vTTEOctWfSn0pkMKa3okq4Gxs5dJE7q1hmWOQ7xcw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.4.0", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0", - "abitype": "1.0.5", - "isows": "1.0.4", - "ws": "8.17.1" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/contracts-permissionless-example/package.json b/contracts-permissionless-example/package.json index 2bc0ad5..e69de29 100644 --- a/contracts-permissionless-example/package.json +++ b/contracts-permissionless-example/package.json @@ -1,17 +0,0 @@ -{ - "name": "permissionless_test", - "version": "1.0.0", - "description": "", - "main": "index.js", - "type": "module", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "run": "bun run index.js" - }, - "author": "", - "license": "ISC", - "dependencies": { - "permissionless": "^0.1.39", - "viem": "^2.17.3" - } -} diff --git a/contracts/package.json b/contracts/package.json index 1b98107..784a31c 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -22,7 +22,8 @@ "prettier:write": "prettier --write \"**/*.{json,md,svg,yml}\"", "test": "forge test", "test:lite": "FOUNDRY_PROFILE=lite forge test", - "test:optimized": "pnpm run build:optimized && FOUNDRY_PROFILE=test-optimized forge test" + "test:optimized": "pnpm run build:optimized && FOUNDRY_PROFILE=test-optimized forge test", + "add:module": "bun run ./test/add-module-to-account.js" }, "dependencies": { "@rhinestone/modulekit": "^0.4.7" diff --git a/contracts/test/abi.js b/contracts/test/abi.js new file mode 100644 index 0000000..5781d68 --- /dev/null +++ b/contracts/test/abi.js @@ -0,0 +1,22 @@ +export const abi = [ + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'config', + outputs: [ + { internalType: 'uint48', name: 'lastAccess', type: 'uint48' }, + { internalType: 'uint48', name: 'timeout', type: 'uint48' }, + { internalType: 'address', name: 'nominee', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'smartAccount', type: 'address' }, + ], + name: 'isInitialized', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, +] diff --git a/contracts/test/add-module-to-account.js b/contracts/test/add-module-to-account.js new file mode 100644 index 0000000..95f5c47 --- /dev/null +++ b/contracts/test/add-module-to-account.js @@ -0,0 +1,98 @@ +import { + ENTRYPOINT_ADDRESS_V07, + createSmartAccountClient, +} from "permissionless"; +import { signerToSafeSmartAccount } from "permissionless/accounts"; +import { + createPimlicoBundlerClient, +} from "permissionless/clients/pimlico"; +import { createPublicClient, http, encodePacked } from "viem"; +import { sepolia } from "viem/chains"; +import {generatePrivateKey, privateKeyToAccount} from "viem/accounts"; +import {erc7579Actions} from "permissionless/actions/erc7579.js"; +import {pimlicoPaymasterActions} from "permissionless/actions/pimlico"; +import {abi} from "./abi"; + +const apiKey = "" + +const privateKey = generatePrivateKey() + +export const bundlerUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}` + +const signer = privateKeyToAccount(privateKey); + + +const publicClient = createPublicClient({ + transport: http("https://rpc.ankr.com/eth_sepolia"), +}) + +const pimlicoBundlerClient = createPimlicoBundlerClient({ + transport: http(bundlerUrl), + entryPoint: ENTRYPOINT_ADDRESS_V07, +}).extend(pimlicoPaymasterActions(ENTRYPOINT_ADDRESS_V07)); + +const safeAccount = await signerToSafeSmartAccount(publicClient, { + signer, + safeVersion: "1.4.1", + entryPoint: ENTRYPOINT_ADDRESS_V07, + safe4337ModuleAddress: "0x3Fdb5BC686e861480ef99A6E3FaAe03c0b9F32e2", + erc7579LaunchpadAddress: "0xEBe001b3D534B9B6E2500FB78E67a1A137f561CE", +}) + +const smartAccountClient = createSmartAccountClient({ + account: safeAccount, + entryPoint: ENTRYPOINT_ADDRESS_V07, + chain: sepolia, + bundlerTransport: http(bundlerUrl), + middleware: { + gasPrice: async () => { + return (await pimlicoBundlerClient.getUserOperationGasPrice()).fast + }, + sponsorUserOperation: pimlicoBundlerClient.sponsorUserOperation + + }, +}).extend(erc7579Actions({ entryPoint: ENTRYPOINT_ADDRESS_V07 })) + +const beneficiary = privateKeyToAccount(privateKey); +const timeout = 100; //in seconds + +async function installModule({smartClient, beneficiaryAddress, timeout, moduleType, hook, account, bundlerClient, moduleAddress, publicClient}) { + const isInitialized = (await publicClient.readContract({ + address: moduleAddress, + abi, + functionName: 'isInitialized', + args: [account.address], + })) + + const module = { + module: moduleAddress, + initData: isInitialized + ? '0x' + : encodePacked(['address', 'uint48'], [beneficiaryAddress, timeout]), + deInitData: '0x', + additionalContext: '0x', + type: moduleType, + hook, + } + + + const opHash = await smartClient.installModule({ + type: module.type, + address: module.module, + context: module.initData, + }); + + const receipt = await bundlerClient.waitForUserOperationReceipt({ hash: opHash }) +} + +installModule({ + smartClient: smartAccountClient, + beneficiaryAddress: beneficiary.address, + timeout, + moduleType: "validator", + hook: '0x', + account: safeAccount, + bundlerClient: pimlicoBundlerClient, + moduleAddress: "0x6A53E204b8A21dfD64516ff27484e6113640CB96", + publicClient +}) \ No newline at end of file