diff --git a/.changeset/fifty-coins-whisper.md b/.changeset/fifty-coins-whisper.md new file mode 100644 index 00000000..f04eaac5 --- /dev/null +++ b/.changeset/fifty-coins-whisper.md @@ -0,0 +1,5 @@ +--- +"permissionless": patch +--- + +Added 7579 actions support diff --git a/bun.lockb b/bun.lockb index 201f4962..52698a02 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 20257823..ffc72a6f 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "type": "module", "sideEffects": false, "devDependencies": { - "vitest": "^1.2.0", "@vitest/coverage-v8": "^1.2.0", "@biomejs/biome": "^1.0.0", "@changesets/changelog-git": "^0.1.14", @@ -61,6 +60,7 @@ "async-mutex": "^0.5.0", "get-port": "^7.0.0", "tsc-alias": "^1.8.8", - "viem": "^2.13.8" + "vitest": "^1.2.0", + "viem": "^2.16.2" } } diff --git a/packages/permissionless-test/mock-aa-infra/alto/constants.ts b/packages/permissionless-test/mock-aa-infra/alto/constants.ts index e1dfbe94..ff273563 100644 --- a/packages/permissionless-test/mock-aa-infra/alto/constants.ts +++ b/packages/permissionless-test/mock-aa-infra/alto/constants.ts @@ -51,6 +51,15 @@ export const SAFE_MULTI_SEND_CREATECALL: Hex = export const SAFE_MULTI_SEND_CALL_ONLY_CREATECALL: Hex = "0x0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b5061019a806100206000396000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b805160205b8181101561015f578083015160f81c6001820184015160601c60158301850151603584018601516055850187016000856000811461012857600181146101385761013d565b6000808585888a5af1915061013d565b600080fd5b50600081141561014c57600080fd5b82605501870196505050505050506100e3565b50505056fea26469706673582212208d297bb003abee230b5dfb38774688f37a6fbb97a82a21728e8049b2acb9b73564736f6c63430007060033" +export const SAFE_7579_LAUNCHPAD_CREATECALL = + "0x000000000000000000000000000000000000000000000000000000000000000060e060405234801561001057600080fd5b50604051612bc8380380612bc883398101604081905261002f91610089565b6001600160a01b03821661005657604051632039d3c960e01b815260040160405180910390fd5b306080526001600160a01b0391821660a0521660c0526100c3565b6001600160a01b038116811461008657600080fd5b50565b6000806040838503121561009c57600080fd5b82516100a781610071565b60208401519092506100b881610071565b809150509250929050565b60805160a05160c051612a9f6101296000396000818161014e015281816104470152610d2401526000818161019f0152818161057501528181610e05015261113c01526000818160eb015281816105200152818161094f0152610e6e0152612a9f6000f3fe6080604052600436106100e15760003560e01c8063928107f91161007f578063d78343d911610059578063d78343d9146102ff578063d9ed0e8f1461031f578063f2dc691d1461033f578063f698da251461035f57600080fd5b8063928107f9146102715780639cfd7cff14610291578063d03c7914146102cf57600080fd5b806319822f7c116100bb57806319822f7c146101e15780633c9de1b81461020f5780634fff40e114610231578063663c87d81461025157600080fd5b806306433b1b1461013c578063137e051e1461018d57806315cca638146101c157600080fd5b36610137576000547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03908116911614610135576040516308e3edd160e41b815260040160405180910390fd5b005b600080fd5b34801561014857600080fd5b506101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561019957600080fd5b506101707f000000000000000000000000000000000000000000000000000000000000000081565b3480156101cd57600080fd5b506101356101dc366004611a57565b610374565b3480156101ed57600080fd5b506102016101fc366004611b4b565b61051a565b604051908152602001610184565b34801561021b57600080fd5b50600080516020612a4a83398151915254610201565b34801561023d57600080fd5b5061013561024c366004611b9e565b61094a565b34801561025d57600080fd5b5061017061026c366004611d28565b610a7a565b34801561027d57600080fd5b5061020161028c366004611f2d565b610b54565b34801561029d57600080fd5b50604080518082018252600f81526e073616665373537392e76312e302e3608c1b6020820152905161018491906120ab565b3480156102db57600080fd5b506102ef6102ea3660046120c5565b610ba6565b6040519015158152602001610184565b34801561030b57600080fd5b5061013561031a3660046120de565b610c4e565b34801561032b57600080fd5b5061013561033a36600461220a565b610dfa565b34801561034b57600080fd5b506102ef61035a3660046120c5565b611082565b34801561036b57600080fd5b506102016110d1565b33301461039457604051630a57d61d60e01b815260040160405180910390fd5b60405163610b592560e01b81526001600160a01b038b166004820152309063610b592590602401600060405180830381600087803b1580156103d557600080fd5b505af11580156103e9573d6000803e3d6000fd5b50506040805160008082526020820190925230935063540fb4f9925090610433565b60408051808201909152600081526060602082015281526020019060019003908161040b5790505b508b8b8b8b8b8b60405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018d8d8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060ff8c166020909101526040516001600160e01b031960e08b901b1681526104dc989796959493929190600401612445565b600060405180830381600087803b1580156104f657600080fd5b505af115801561050a573d6000803e3d6000fd5b5050505050505050505050505050565b600080547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161461056a576040516308e3edd160e41b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105b357604051632039d3c960e01b815260040160405180910390fd5b6105c060608501856124b8565b6105cf916004916000916124fe565b6105d891612528565b6001600160e01b03191663d9ed0e8f60e01b146106085760405163c3d40f7760e01b815260040160405180910390fd5b600061061760608601866124b8565b6106259160049082906124fe565b8101906106329190611f2d565b905061064a600080516020612a4a8339815191525490565b61065382610b54565b146106715760405163278328b160e21b815260040160405180910390fd5b600080866020013590508060601c915060008360a001516001600160a01b03168460c001516040516024016106a69190612560565b60408051601f19818403018152918152602080830180516001600160e01b0316633cd56b0760e11b17905290516106e09291339101612573565b60408051601f19818403018152908290526106fa916125a5565b6000604051808303816000865af19150503d8060008114610737576040519150601f19603f3d011682016040523d82523d6000602084013e61073c565b606091505b505090508061075e5760405163c3d40f7760e01b815260040160405180910390fd5b60c084015151600090815b818110156108805760008760c001518281518110610789576107896125c1565b6020026020010151600001519050806001600160a01b0316636d61fe708960c0015184815181106107bc576107bc6125c1565b6020026020010151602001516040518263ffffffff1660e01b81526004016107e491906120ab565b600060405180830381600087803b1580156107fe57600080fd5b505af1158015610812573d6000803e3d6000fd5b505060408051600181526001600160a01b03851660208201527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123935001905060405180910390a1866001600160a01b0316816001600160a01b03160361087757600193505b50600101610769565b5081156108ff57604051639700320360e01b81526001600160a01b038616906397003203906108b5908d908d906004016125d7565b6020604051808303816000875af11580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906126db565b965061092b565b60008060006109138960a001518d8f61112a565b925092509250610925831582846112a9565b99505050505b871561093d576000806000808b335af1505b5050505050509392505050565b6000547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03908116911614610999576040516308e3edd160e41b815260040160405180910390fd5b60006109b1600080516020612a4a8339815191525490565b146109cf5760405163d4d496e560e01b815260040160405180910390fd5b6109e584600080516020612a4a83398151915255565b6001600160a01b03831615610a74576000836001600160a01b03168383604051610a109291906126f4565b600060405180830381855af49150503d8060008114610a4b576040519150601f19603f3d011682016040523d82523d6000602084013e610a50565b606091505b5050905080610a7257604051631f57fed560e31b815260040160405180910390fd5b505b50505050565b6000818051906020012083604051602001610a9f929190918252602082015260400190565b60405160208183030381529060405280519060200120925060ff60f81b858486896001600160a01b0316604051602001610ada929190612704565b60405160208183030381529060405280519060200120604051602001610b3294939291906001600160f81b031994909416845260609290921b6001600160601b03191660018401526015830152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098610b89989097969101612726565b604051602081830303815290604052805190602001209050919050565b600081600881901b610bbc82600160f81b6112e1565b15610bca5760019250610c0d565b610bd58260006112e1565b15610be35760019250610c0d565b610bf5826001600160f81b03196112e1565b15610c035760019250610c0d565b5060009392505050565b828015610c205750610c208160006112e1565b15610c2c575050919050565b828015610c425750610c4281600160f81b6112e1565b15610c03575050919050565b60405163610b592560e01b81526001600160a01b038d166004820152309063610b592590602401600060405180830381600087803b158015610c8f57600080fd5b505af1158015610ca3573d6000803e3d6000fd5b505060405163f08a032360e01b81526001600160a01b038f16600482015230925063f08a03239150602401600060405180830381600087803b158015610ce857600080fd5b505af1158015610cfc573d6000803e3d6000fd5b50505050306001600160a01b031663540fb4f98c8c8c8c8c8c8c8c60405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e8e8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060ff8d166020909101526040516001600160e01b031960e08c901b168152610dba999897969594939291906004016127a3565b600060405180830381600087803b158015610dd457600080fd5b505af1158015610de8573d6000803e3d6000fd5b50505050505050505050505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e4357604051632039d3c960e01b815260040160405180910390fd5b610e506020820182612818565b600080546001600160a01b0319166001600160a01b039283161790557f000000000000000000000000000000000000000000000000000000000000000016610e9e6080830160608401612818565b6001600160a01b031614610ec557604051633007073760e01b815260040160405180910390fd5b6302b994c760e31b610eda60808301836124b8565b610ee9916004916000916124fe565b610ef291612528565b6001600160e01b03191614610f1a57604051633007073760e01b815260040160405180910390fd5b3063b63e800d610f2d6020840184612835565b6040850135610f426080870160608801612818565b610f4f60808801886124b8565b610f5f60c08a0160a08b01612818565b60008060006040518b63ffffffff1660e01b8152600401610f899a9998979695949392919061287e565b600060405180830381600087803b158015610fa357600080fd5b505af1158015610fb7573d6000803e3d6000fd5b50506000600080516020612a4a8339815191525550610fd39050565b600080610fe660c0840160a08501612818565b6001600160a01b0316610ffc60e08501856124b8565b3060405160200161100f93929190612935565b60408051601f1981840301815290829052611029916125a5565b6000604051808303816000865af19150503d8060008114611066576040519150601f19603f3d011682016040523d82523d6000602084013e61106b565b606091505b50915091508161107d57805160208201fd5b505050565b60006001820361109457506001919050565b600282036110a457506001919050565b600382036110b457506001919050565b600482036110c457506001919050565b506000919050565b919050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b600080600080600080366000611160897f00000000000000000000000000000000000000000000000000000000000000006112f8565b8451602086012094995092975090955093509150600061118360608c018c6124b8565b6111919160049082906124fe565b81019061119e9190611f2d565b905060006111e885858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505060408501518692915061152b565b90506111f38161181a565b60208201516112018161181a565b61120a81611826565b80516000805b8281101561128b57600061124685838151811061122f5761122f6125c1565b60200260200101518761182f90919063ffffffff16565b509050801561128257826112598161296c565b93505086604001518310611282575060019e50999c50979a506112a09950505050505050505050565b50600101611210565b5060009d50989b509699505050505050505050505b93509350939050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b856112d15760006112d4565b60015b60ff161717949350505050565b6001600160f81b0319828116908216145b92915050565b60606000803681818161130f6101008a018a6124b8565b90925090506113226006600083856124fe565b61132b91612985565b60d01c955061133e600c600683856124fe565b61134791612985565b60d01c945061135981600c81856124fe565b9350935050506000604051806101c001604052807fc03dfc11d8b10bf9cf703d558958c8c42777f785d998c62060d85a4f0ef6ea7f60001b81526020018960000160208101906113a99190612818565b6001600160a01b03168152602001896020013581526020018980604001906113d191906124b8565b6040516113df9291906126f4565b60405190819003902081526020016113fa60608b018b6124b8565b6040516114089291906126f4565b6040518091039020815260200161141e8a611852565b6001600160801b031681526020016114358a611862565b6001600160801b031681526020018960a0013581526020016114568a611877565b6001600160801b0316815260200161146d8a611886565b6001600160801b0316815260200161148860e08b018b6124b8565b6040516114969291906126f4565b6040805191829003909120825265ffffffffffff80891660208401528716908201526001600160a01b0389166060909101526101c08120909150601960f81b600160f81b6114e26110d1565b6040516001600160f81b03199384166020820152929091166021830152602282015260428101829052606201604051602081830303815290604052965050509295509295909350565b6060600061153a8360416129bb565b8451909150836001600160401b0381111561155757611557611c28565b604051908082528060200260200182016040528015611580578160200160208202803683370190505b509250818110156115a457604051638baa579f60e01b815260040160405180910390fd5b60005b84811015611810576000806000806115d78a86604102016020810151604082015160609092015160001a92909190565b9250925092508260ff1660000361176f5790925082906041811015611625576040516338a245ff60e11b81526004810182905260006024820181905260448201526064015b60405180910390fd5b856116318260206129d2565b1115611661576040516338a245ff60e11b815260048101829052600060248201526044810187905260640161161c565b6020818b0181015190879082906116799085906129d2565b61168391906129d2565b11156116b3576040516338a245ff60e11b815260048101839052602481018290526044810188905260640161161c565b60606020838d01019050631626ba7e60e01b6001600160e01b031916866001600160a01b0316631626ba7e8f846040518363ffffffff1660e01b81526004016116fd9291906129e5565b602060405180830381865afa15801561171a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173e9190612a06565b6001600160e01b03191614611768578060405163605d348960e01b815260040161161c91906120ab565b50506117d5565b601e8360ff1611156117c6576117bf6117ad8c6020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c60042090565b6117b8600486612a30565b848461189b565b93506117d5565b6117d28b84848461189b565b93505b838886815181106117e8576117e86125c1565b6001600160a01b03909216602092830291909101909101525050600190920191506115a79050565b5050509392505050565b611823816118d9565b50565b6118238161192e565b60008061184784846001600160a01b03166000611977565b909590945092505050565b60006112f2826080013560801c90565b60006001600160801b036080830135166112f2565b600060c082013560801c6112f2565b60006001600160801b0360c0830135166112f2565b60006040518560005260ff85166020528360405282606052602060406080600060015afa5060006060523d6060185191508060405250949350505050565b8051600082528060051b82016020601f198185015b8201838111611926578051828201805182811161190d575050506118ee565b5b818601528301805182811161190e57508401526118ee565b505050915250565b6002815110611823576020810160408201600183510160051b83015b815183511461195e57602083019250815183525b60208201915080820361194a57505081900360051c9052565b60008060001960018651600087870197505b81830160011c94508460051b89015187019050878114828411176119c3578088116119b8578385019150611989565b600185019250611989565b84151597148716989290930190950295509350505050565b6001600160a01b038116811461182357600080fd5b80356110cc816119db565b60008083601f840112611a0d57600080fd5b5081356001600160401b03811115611a2457600080fd5b6020830191508360208260051b8501011115611a3f57600080fd5b9250929050565b803560ff811681146110cc57600080fd5b60008060008060008060008060008060c08b8d031215611a7657600080fd5b611a7f8b6119f0565b995060208b01356001600160401b03811115611a9a57600080fd5b611aa68d828e016119fb565b909a5098505060408b01356001600160401b03811115611ac557600080fd5b611ad18d828e016119fb565b90985096505060608b01356001600160401b03811115611af057600080fd5b611afc8d828e016119fb565b90965094505060808b01356001600160401b03811115611b1b57600080fd5b611b278d828e016119fb565b9094509250611b3a905060a08c01611a46565b90509295989b9194979a5092959850565b600080600060608486031215611b6057600080fd5b83356001600160401b03811115611b7657600080fd5b84016101208187031215611b8957600080fd5b95602085013595506040909401359392505050565b60008060008060608587031215611bb457600080fd5b843593506020850135611bc6816119db565b925060408501356001600160401b03811115611be157600080fd5b8501601f81018713611bf257600080fd5b80356001600160401b03811115611c0857600080fd5b876020828401011115611c1a57600080fd5b949793965060200194505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611c6057611c60611c28565b60405290565b60405161010081016001600160401b0381118282101715611c6057611c60611c28565b604051601f8201601f191681016001600160401b0381118282101715611cb157611cb1611c28565b604052919050565b600082601f830112611cca57600080fd5b81356001600160401b03811115611ce357611ce3611c28565b611cf6601f8201601f1916602001611c89565b818152846020838601011115611d0b57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215611d4057600080fd5b8535611d4b816119db565b94506020860135611d5b816119db565b935060408601356001600160401b03811115611d7657600080fd5b611d8288828901611cb9565b9350506060860135915060808601356001600160401b03811115611da557600080fd5b611db188828901611cb9565b9150509295509295909350565b60006001600160401b03821115611dd757611dd7611c28565b5060051b60200190565b600082601f830112611df257600080fd5b8135611e05611e0082611dbe565b611c89565b8082825260208201915060208360051b860101925085831115611e2757600080fd5b602085015b83811015611e4d578035611e3f816119db565b835260209283019201611e2c565b5095945050505050565b600082601f830112611e6857600080fd5b8135611e76611e0082611dbe565b8082825260208201915060208360051b860101925085831115611e9857600080fd5b602085015b83811015611e4d5780356001600160401b03811115611ebb57600080fd5b86016040818903601f19011215611ed157600080fd5b611ed9611c3e565b6020820135611ee7816119db565b815260408201356001600160401b03811115611f0257600080fd5b611f118a602083860101611cb9565b6020830152508085525050602083019250602081019050611e9d565b600060208284031215611f3f57600080fd5b81356001600160401b03811115611f5557600080fd5b82016101008185031215611f6857600080fd5b611f70611c66565b611f79826119f0565b815260208201356001600160401b03811115611f9457600080fd5b611fa086828501611de1565b60208301525060408281013590820152611fbc606083016119f0565b606082015260808201356001600160401b03811115611fda57600080fd5b611fe686828501611cb9565b608083015250611ff860a083016119f0565b60a082015260c08201356001600160401b0381111561201657600080fd5b61202286828501611e57565b60c08301525060e08201356001600160401b0381111561204157600080fd5b61204d86828501611cb9565b60e083015250949350505050565b60005b8381101561207657818101518382015260200161205e565b50506000910152565b6000815180845261209781602086016020860161205b565b601f01601f19169290920160200192915050565b6020815260006120be602083018461207f565b9392505050565b6000602082840312156120d757600080fd5b5035919050565b60008060008060008060008060008060008060e08d8f03121561210057600080fd5b6121098d6119f0565b9b506001600160401b0360208e0135111561212357600080fd5b6121338e60208f01358f016119fb565b909b5099506001600160401b0360408e0135111561215057600080fd5b6121608e60408f01358f016119fb565b90995097506001600160401b0360608e0135111561217d57600080fd5b61218d8e60608f01358f016119fb565b90975095506001600160401b0360808e013511156121aa57600080fd5b6121ba8e60808f01358f016119fb565b90955093506001600160401b0360a08e013511156121d757600080fd5b6121e78e60a08f01358f016119fb565b90935091506121f860c08e01611a46565b90509295989b509295989b509295989b565b60006020828403121561221c57600080fd5b81356001600160401b0381111561223257600080fd5b820161010081850312156120be57600080fd5b600082825180855260208501945060208160051b8301016020850160005b838110156122b557848303601f19018852815180516001600160a01b0316845260209081015160409185018290529061229e9085018261207f565b6020998a0199909450929092019150600101612263565b50909695505050505050565b6000808335601e198436030181126122d857600080fd5b83016020810192503590506001600160401b038111156122f757600080fd5b803603821315611a3f57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008383855260208501945060208460051b8201018360005b868110156122b557838303601f19018852813536879003603e1901811261236e57600080fd5b8601803561237b816119db565b6001600160a01b0316845261239360208201826122c1565b9150604060208601526123aa604086018383612306565b60209a8b019a90955093909301925050600101612348565b600081518084526020840193506020830160005b828110156123fd5781516001600160a01b03168652602095860195909101906001016123d6565b5093949350505050565b60018060a01b038151168252600060208201516060602085015261242e60608501826123c2565b60409384015160ff16949093019390935250919050565b60a08152600061245860a083018b612245565b828103602084015261246b818a8c61232f565b9050828103604084015261248081888a61232f565b9050828103606084015261249581868861232f565b905082810360808401526124a98185612407565b9b9a5050505050505050505050565b6000808335601e198436030181126124cf57600080fd5b8301803591506001600160401b038211156124e957600080fd5b602001915036819003821315611a3f57600080fd5b6000808585111561250e57600080fd5b8386111561251b57600080fd5b5050820193919092039150565b80356001600160e01b03198116906004841015612559576001600160e01b0319600485900360031b81901b82161691505b5092915050565b6020815260006120be6020830184612245565b6000835161258581846020880161205b565b60609390931b6001600160601b0319169190920190815260140192915050565b600082516125b781846020870161205b565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b604081526125f8604082016125eb856119f0565b6001600160a01b03169052565b60208301356060820152600061261160408501856122c1565b610120608085015261262861016085018284612306565b91505061263860608601866122c1565b848303603f190160a086015261264f838284612306565b608088013560c08781019190915260a089013560e08089019190915290890135610100880152909350612687925087019050866122c1565b848303603f190161012086015261269f838284612306565b925050506126b16101008601866122c1565b848303603f19016101408601526126c9838284612306565b93505050508260208301529392505050565b6000602082840312156126ed57600080fd5b5051919050565b8183823760009101908152919050565b6000835161271681846020880161205b565b9190910191825250602001919050565b6001600160a01b038816815260e06020820181905260009061274a908301896123c2565b604083018890526001600160a01b03871660608401528281036080840152612772818761207f565b6001600160a01b03861660a085015283810360c085015290506127958185612245565b9a9950505050505050505050565b60a0815260006127b760a083018b8d61232f565b82810360208401526127ca818a8c61232f565b905082810360408401526127df81888a61232f565b905082810360608401526127f481868861232f565b905082810360808401526128088185612407565b9c9b505050505050505050505050565b60006020828403121561282a57600080fd5b81356120be816119db565b6000808335601e1984360301811261284c57600080fd5b8301803591506001600160401b0382111561286657600080fd5b6020019150600581901b3603821315611a3f57600080fd5b61010080825281018a905260008b6101208301825b8d8110156128c35782356128a6816119db565b6001600160a01b0316825260209283019290910190600101612893565b508b60208501526128df604085018c6001600160a01b03169052565b83810360608501526128f2818a8c612306565b9250505061290b60808301876001600160a01b03169052565b6001600160a01b03851660a08301528360c08301526124a960e08301846001600160a01b03169052565b8284823760609190911b6001600160601b0319169101908152601401919050565b634e487b7160e01b600052601160045260246000fd5b60006001820161297e5761297e612956565b5060010190565b80356001600160d01b03198116906006841015612559576001600160d01b031960069490940360031b84901b1690921692915050565b80820281158282048414176112f2576112f2612956565b808201808211156112f2576112f2612956565b8281526040602082015260006129fe604083018461207f565b949350505050565b600060208284031215612a1857600080fd5b81516001600160e01b0319811681146120be57600080fd5b60ff82811682821603908111156112f2576112f261295656fe982e06ee6a56dfc0f1ac189a5d23506361ca0a3ce45a9c7b8d33d65d43746a24a2646970667358221220b9f8a86409c3671f7b19131d085b34f0ba682783524a0bae7bea00939bae967d64736f6c634300081a00330000000000000000000000000000000071727de22e5e9d8baf0edac6f37da03200000000000000000000000025a4b2f363678e13a0a5db79b712de00347a593e" + +export const SAFE_7579_REGISTRY_CREATECALL: Hex = + "0x00000000000000000000000000000000000000000000000000000000000000006080604052348015600f57600080fd5b506103d18061001f6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063529562a11161005b578063529562a1146100bf57806396fb7217146100d2578063c23697a8146100e0578063f05c04e1146100f157600080fd5b80630bb30abc146100825780632ed94467146100985780634c13560c146100ad575b600080fd5b6100966100903660046101c8565b50505050565b005b6100966100a6366004610222565b5050505050565b6100966100bb366004610284565b5050565b6100966100cd3660046102b7565b505050565b6100966100bb3660046102f4565b6100966100ee36600461031e565b50565b6100966100ff366004610340565b6040513381527fb8a00d6d8ca1be30bfec34d8f97e55f0f0fd9eeb7fb46e030516363d4cfe1ad69060200160405180910390a16040517fb6d9a72244037f5f1de04d8ff74cd328f1574efc59a02163d0fec0554871974690600090a1505050565b80356001600160a01b038116811461017757600080fd5b919050565b60008083601f84011261018e57600080fd5b50813567ffffffffffffffff8111156101a657600080fd5b6020830191508360208260051b85010111156101c157600080fd5b9250929050565b600080600080606085870312156101de57600080fd5b6101e785610160565b9350602085013567ffffffffffffffff81111561020357600080fd5b61020f8782880161017c565b9598909750949560400135949350505050565b60008060008060006080868803121561023a57600080fd5b61024386610160565b945060208601359350604086013567ffffffffffffffff81111561026657600080fd5b6102728882890161017c565b96999598509660600135949350505050565b6000806040838503121561029757600080fd5b6102a083610160565b91506102ae60208401610160565b90509250929050565b6000806000606084860312156102cc57600080fd5b6102d584610160565b92506102e360208501610160565b929592945050506040919091013590565b6000806040838503121561030757600080fd5b61031083610160565b946020939093013593505050565b60006020828403121561033057600080fd5b61033982610160565b9392505050565b60008060006040848603121561035557600080fd5b833560ff8116811461036657600080fd5b9250602084013567ffffffffffffffff81111561038257600080fd5b61038e8682870161017c565b949790965093945050505056fea2646970667358221220181467498dc4fab0c64814a0965539f6b8e992676b95c29db59b1cc06cd50f0f64736f6c634300081a0033" + +export const SAFE_7579_MODULE_CREATECALL: Hex = + "0x000000000000000000000000000000000000000000000000000000000000000060a0604052348015600f57600080fd5b50604051601a906046565b604051809103906000f0801580156035573d6000803e3d6000fd5b506001600160a01b03166080526053565b6109e180614d7483390190565b608051614cb96100bb60003960008181610f340152818161112c0152818161128d01528181611ad601528181611f2d015281816120070152818161209e0152818161213501528181613248015281816133000152818161385b015261397b0152614cb96000f3fe6080604052600436106101235760003560e01c8063b0d691fe116100a0578063e9ae5c5311610064578063e9ae5c5314610479578063ea5f61d014610499578063eab77e17146104b9578063f2dc691d146104d9578063f698da25146104f95761012a565b8063b0d691fe1461039e578063b875d5d8146103c1578063d03c79141461040c578063d691c9641461042c578063d828435d146104595761012a565b80635faac46b116100e75780635faac46b146102d257806379aad60e146103005780639517e29f146103205780639cfd7cff14610340578063a71763a81461037e5761012a565b80630a664dba146101d5578063112d3a7d146102195780631626ba7e1461024957806319822f7c14610282578063540fb4f9146102b05761012a565b3661012a57005b600036606060003560e01c63bc197c81811463f23a6e6182141763150b7a028214171561015b57806020526020603cf35b50336000818152600460209081526040808320546001600160e01b031984351680855260058452828520958552949092528220546001600160a01b0391821692911690806101a9848461050e565b915091506101b788886105cc565b95506101c5848484846106df565b5050505050915050805190602001f35b3480156101e157600080fd5b50336000908152600460205260409020546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561022557600080fd5b50610239610234366004613c93565b610762565b6040519015158152602001610210565b34801561025557600080fd5b50610269610264366004613cee565b6107bf565b6040516001600160e01b03199091168152602001610210565b34801561028e57600080fd5b506102a261029d366004613d39565b610b35565b604051908152602001610210565b3480156102bc57600080fd5b506102d06102cb366004613de8565b610c49565b005b3480156102de57600080fd5b506102f26102ed366004613ee4565b610cf9565b604051610210929190613f10565b34801561030c57600080fd5b506102d061031b366004613f73565b610d15565b34801561032c57600080fd5b506102d061033b366004613c93565b610dd9565b34801561034c57600080fd5b50604080518082018252600f81526e073616665373537392e76312e302e3608c1b602082015290516102109190614004565b34801561038a57600080fd5b506102d0610399366004613c93565b610fa4565b3480156103aa57600080fd5b506f71727de22e5e9d8baf0edac6f37da0326101fc565b3480156103cd57600080fd5b506101fc6103dc36600461402d565b6001600160e01b03191660009081526005602090815260408083203384529091529020546001600160a01b031690565b34801561041857600080fd5b5061023961042736600461404a565b6112cb565b34801561043857600080fd5b5061044c610447366004613cee565b611373565b6040516102109190614063565b34801561046557600080fd5b506102a26104743660046140c8565b61145c565b34801561048557600080fd5b506102d0610494366004613cee565b6114fc565b3480156104a557600080fd5b506102f26104b4366004613ee4565b611899565b3480156104c557600080fd5b506102d06104d4366004614112565b6118aa565b3480156104e557600080fd5b506102396104f436600461404a565b611919565b34801561050557600080fd5b506102a2611968565b6060806001600160a01b0384161561058e576105753385600061052f6119c1565b3460003660405160240161054694939291906141a1565b60408051601f198184030181529190526020810180516001600160e01b031663d68f602560e01b1790526119cd565b91508180602001905181019061058b919061428a565b91505b6001600160a01b038316156105c5576105ac3384600061052f6119c1565b9050808060200190518101906105c2919061428a565b90505b9250929050565b600080356001600160e01b031916815260036020908152604080832033845290915290208054606091906001600160a01b03811690600160a01b900460f81b8161063c57604051632464e76d60e11b81526001600160e01b03196000351660048201526024015b60405180910390fd5b61064a81607f60f91b611a76565b1561068e576106843383888861065e6119c1565b604051602001610670939291906142be565b604051602081830303815290604052611a88565b93505050506106d9565b610699816000611a76565b156106d5576106843383600089896106af6119c1565b6040516020016106c1939291906142be565b6040516020818303038152906040526119cd565b5050505b92915050565b6001600160a01b038416156107355761073533856000856040516024016107069190614004565b60408051601f198184030181529190526020810180516001600160e01b0316630b9dfbed60e11b179052611b5d565b6001600160a01b0383161561075c5761075c33846000846040516024016107069190614004565b50505050565b60006001850361077c5761077584611bfc565b90506107b7565b6002850361078d5761077584611c0a565b600385036107a057610775848484611c18565b600485036107b357610775848484611c64565b5060005b949350505050565b600033828203610959576000610890826001600160a01b031663f698da256040518163ffffffff1660e01b8152600401602060405180830381865afa15801561080c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083091906142e4565b60408051602081018a90527f60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca91015b60408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052611c9f565b8051602090910120604051635ae6bd3760e01b8152600481018290529091506001600160a01b03831690635ae6bd3790602401602060405180830381865afa1580156108e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090491906142e4565b6000036109475760405162461bcd60e51b815260206004820152601160248201527012185cda081b9bdd08185c1c1c9bdd9959607a1b6044820152606401610633565b50630b135d3f60e11b9150610b2e9050565b600061096860148286886142fd565b61097191614327565b60601c9050801580610989575061098781611bfc565b155b15610ab3576000610a28836001600160a01b031663f698da256040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f591906142e4565b60408051602081018b90527f60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca910161085f565b805160208201209091506001600160a01b03841663934f3a118284610a508a6014818e6142fd565b6040518563ffffffff1660e01b8152600401610a6f9493929190614374565b60006040518083038186803b158015610a8757600080fd5b505afa158015610a9b573d6000803e3d6000fd5b50630b135d3f60e11b9750610b2e9650505050505050565b6000610b123383610ac26119c1565b8a610ad08a6014818e6142fd565b604051602401610ae394939291906141a1565b60408051601f198184030181529190526020810180516001600160e01b0316637aa8f17760e11b179052611a88565b905080806020019051810190610b2891906143ab565b93505050505b9392505050565b60006f71727de22e5e9d8baf0edac6f37da032610b506119c1565b6001600160a01b031614610b7757604051635629665f60e11b815260040160405180910390fd5b6020840135606081901c90811580610b955750610b9382611bfc565b155b15610baa57610ba386611d19565b9250610c0f565b6000610bf5338460008a8a604051602401610bc692919061440d565b60408051601f198184030181529190526020810180516001600160e01b0316639700320360e01b1790526119cd565b905080806020019051810190610c0b91906142e4565b9350505b8315610c4057610c40336f71727de22e5e9d8baf0edac6f37da0328660405180602001604052806000815250611b5d565b50509392505050565b6f71727de22e5e9d8baf0edac6f37da032610c626119c1565b6001600160a01b03161480610c8f5750610c7a6119c1565b6001600160a01b0316336001600160a01b0316145b610cac57604051635629665f60e11b815260040160405180910390fd5b610cde610cbc6020830183614511565b610cc9602084018461452e565b610cd96060860160408701614577565b611dce565b610cee8989898989898989611e85565b505050505050505050565b60606000610d0a60013386866121a4565b915091509250929050565b6f71727de22e5e9d8baf0edac6f37da032610d2e6119c1565b6001600160a01b03161480610d5b5750610d466119c1565b6001600160a01b0316336001600160a01b0316145b610d7857604051635629665f60e11b815260040160405180910390fd5b610d83600133612368565b8060005b8181101561075c5736848483818110610da257610da2614592565b9050602002810190610db491906145a8565b9050610dd033610dc76020840184614511565b600191906123e3565b50600101610d87565b336000908152600460209081526040808320547fd00bcad91b775f25eb0aee15808d12dfdaa6dc5a7d6b754e26f9c205d2a3b8df909252822054639517e29f60e01b926001600160a01b03928316929091169080610e37848461050e565b91509150610e526f71727de22e5e9d8baf0edac6f37da03290565b6001600160a01b0316610e636119c1565b6001600160a01b03161480610e905750610e7b6119c1565b6001600160a01b0316336001600160a01b0316145b610ead57604051635629665f60e11b815260040160405180910390fd5b606060018a03610ec957610ec28989896124d8565b9050610f2e565b60028a03610edc57610ec2898989612534565b60038a03610eef57610ec289898961254f565b60048a03610f0257610ec28989896126ce565b89610f1257610ec289898961286e565b60405163041c38b360e41b8152600481018b9052602401610633565b610f97337f00000000000000000000000000000000000000000000000000000000000000008c8c85604051602401610f68939291906145c8565b60408051601f198184030181529190526020810180516001600160e01b0316639517e29f60e01b179052612a1f565b50610cee848484846106df565b336000908152600460209081526040808320547fc45a7acaba78a7b4c4432b604d301355b314c0a7811768a1ee2563c9d34ca4e09092529091205484916314e2ec7560e31b916001600160a01b0391821691908116908416821480159061101d5750806001600160a01b0316846001600160a01b031614155b156111a35760008061102f848461050e565b9150915061104a6f71727de22e5e9d8baf0edac6f37da03290565b6001600160a01b031661105b6119c1565b6001600160a01b0316148061108857506110736119c1565b6001600160a01b0316336001600160a01b0316145b6110a557604051635629665f60e11b815260040160405180910390fd5b606060018b036110c1576110ba8a8a8a612ab8565b9050611126565b60028b036110d4576110ba8a8a8a612ae1565b60038b036110e7576110ba8a8a8a612b02565b60048b036110fa576110ba8a8a8a612b4e565b8a61110a576110ba8a8a8a612c06565b60405163041c38b360e41b8152600481018c9052602401610633565b61118f337f00000000000000000000000000000000000000000000000000000000000000008d8d85604051602401611160939291906145c8565b60408051601f198184030181529190526020810180516001600160e01b0316637827252560e01b179052612d59565b5061119c848484846106df565b50506112c1565b6f71727de22e5e9d8baf0edac6f37da0326111bc6119c1565b6001600160a01b031614806111e957506111d46119c1565b6001600160a01b0316336001600160a01b0316145b61120657604051635629665f60e11b815260040160405180910390fd5b6060600189036112225761121b888888612ab8565b9050611287565b600289036112355761121b888888612ae1565b600389036112485761121b888888612b02565b6004890361125b5761121b888888612b4e565b8861126b5761121b888888612c06565b60405163041c38b360e41b8152600481018a9052602401610633565b610cee337f00000000000000000000000000000000000000000000000000000000000000008b8b85604051602401611160939291906145c8565b5050505050505050565b600081600881901b6112e182600160f81b611a76565b156112ef5760019250611332565b6112fa826000611a76565b156113085760019250611332565b61131a826001600160f81b0319611a76565b156113285760019250611332565b5060009392505050565b8280156113455750611345816000611a76565b15611351575050919050565b828015611367575061136781600160f81b611a76565b15611328575050919050565b60606113856113806119c1565b611c0a565b6113b6576113916119c1565b604051635c93ff2f60e11b81526001600160a01b039091166004820152602401610633565b336000908152600460209081526040808320547f4162c930ade27880570b0eb31efbc8a626b97e81a40ced27163509dfe16398829092528220546335a4725960e21b926001600160a01b03928316929091169080611414848461050e565b915091506114206119c1565b600261142c8282612e0f565b8a600881901b61143e81838e8e612e9a565b995050505050611450848484846106df565b50505050509392505050565b6000602082901b640100000000600160c01b03166f71727de22e5e9d8baf0edac6f37da032604051631aab3f0d60e11b81526001600160a01b0386811660048301526001600160c01b038416602483015291909116906335567e1a90604401602060405180830381865afa1580156114d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b791906142e4565b336000908152600460209081526040808320547fccfe1b2bef70acd8e661aeb5430e147f4c75cb320972acba718a28da428e1a3090925282205463e9ae5c5360e01b926001600160a01b0392831692909116908061155a848461050e565b915091506115756f71727de22e5e9d8baf0edac6f37da03290565b6001600160a01b03166115866119c1565b6001600160a01b031614806115b3575061159e6119c1565b6001600160a01b0316336001600160a01b0316145b6115d057604051635629665f60e11b815260040160405180910390fd5b87600881901b336115e2826000611a76565b1561173b576115f583600160f81b611a76565b156116165789358a0160208101903561160f838383613242565b505061188a565b611621836000611a76565b15611689576000803660006116368e8e6132a9565b935093509350935061168085858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b5d92505050565b5050505061188a565b61169b836001600160f81b0319611a76565b156117205760006116af6014828c8e6142fd565b6116b891614327565b60601c90503660008c8c60149080926116d3939291906142fd565b91509150611718848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a1f92505050565b50505061188a565b82604051632e5bf3f960e21b815260040161063391906145fb565b61174982600160f81b611a76565b1561186f5761175c83600160f81b611a76565b156117765789358a0160208101903561160f8383836132fa565b611781836000611a76565b156117e0576000803660006117968e8e6132a9565b935093509350935061168085858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061336192505050565b6117f2836001600160f81b0319611a76565b156117205760006118066014828c8e6142fd565b61180f91614327565b60601c90503660008c8c601490809261182a939291906142fd565b91509150611718848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d5992505050565b816040516308c3ee0360e11b815260040161063391906145fb565b5050506112c1848484846106df565b60606000610d0a60023386866121a4565b6f71727de22e5e9d8baf0edac6f37da0326118c36119c1565b6001600160a01b031614806118f057506118db6119c1565b6001600160a01b0316336001600160a01b0316145b61190d57604051635629665f60e11b815260040160405180910390fd5b61075c84848484611dce565b60006001820361192b57506001919050565b6002820361193b57506001919050565b6003820361194b57506001919050565b6004820361195b57506001919050565b506000919050565b919050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b60131936013560601c90565b60606000856001600160a01b0316635229073f86868660006040518563ffffffff1660e01b8152600401611a049493929190614648565b6000604051808303816000875af1158015611a23573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a4b919081019061468e565b9250905080611a6d57604051632b3f6d1160e21b815260040160405180910390fd5b50949350505050565b6001600160f81b031990811691161490565b606060008383604051602401611a9f9291906146db565b60408051601f198184030181529181526020820180516001600160e01b0316636a22165760e01b17905251909150600090611b00907f00000000000000000000000000000000000000000000000000000000000000009084906024016146db565b60408051601f19818403018152919052602080820180516001600160e01b031663b4faba0960e01b17815282519293509091600091895afa5060203d036040519350808401604052806020853e50600051610c4057825160208401fd5b60405163468721a760e01b81526000906001600160a01b0386169063468721a790611b92908790879087908790600401614648565b6020604051808303816000875af1158015611bb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd591906146ff565b905080611bf557604051632b3f6d1160e21b815260040160405180910390fd5b5050505050565b60006106d960013384613417565b60006106d960023384613417565b600080611c278385018561402d565b6001600160e01b03191660009081526003602090815260408083203384529091529020546001600160a01b03908116908616149150509392505050565b60008080611c7484860186614729565b915091506000611c84838361345b565b6001600160a01b039081169088161493505050509392505050565b6060601960f81b600160f81b858585604051602001611cbf929190614755565b60408051808303601f190181529082905280516020918201206001600160f81b0319958616918301919091529290931660218401526022830152604282015260620160405160208183030381529060405290509392505050565b60008080803681611d3a876f71727de22e5e9d8baf0edac6f37da0326134f1565b8451602086012060405163934f3a1160e01b8152959a5093985091965094509250339163934f3a1191611d7591899087908790600401614374565b60006040518083038186803b158015611d8d57600080fd5b505afa925050508015611d9e575060015b611db557611dae60018486613724565b9550611dc4565b611dc160008486613724565b95505b5050505050919050565b33600090815260208190526040902080546001600160a01b0319166001600160a01b03861690811790915515611e4957611e4933856000848787604051602401611e1a9392919061477b565b60408051601f198184030181529190526020810180516001600160e01b031663f05c04e160e01b179052611b5d565b6040516001600160a01b0385169033907f9452c8fb077c3ea8f28a77c87488af657b1e44d010ad9a5992d73870da040e9490600090a350505050565b3360009081527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f602052604090205460609088906001600160a01b0316611f7d57611ed1600133612368565b60005b81811015611f7757368b8b83818110611eef57611eef614592565b9050602002810190611f0191906145a8565b9050611f25611f136020830183614511565b611f2060208401846147d3565b6124d8565b9350611f6e337f00000000000000000000000000000000000000000000000000000000000000006001611f5b6020860186614511565b88604051602401610f68939291906145c8565b50600101611ed4565b50611f9e565b8015611f9e5760405163d8e3ed1b60e01b8152336004820152602401610633565b611fa9600233612368565b508560005b8181101561203e5736898983818110611fc957611fc9614592565b9050602002810190611fdb91906145a8565b9050611fff611fed6020830183614511565b611ffa60208401846147d3565b612534565b9350612035337f00000000000000000000000000000000000000000000000000000000000000006002611f5b6020860186614511565b50600101611fae565b5084905060005b818110156120d5573687878381811061206057612060614592565b905060200281019061207291906145a8565b90506120966120846020830183614511565b61209160208401846147d3565b61254f565b93506120cc337f00000000000000000000000000000000000000000000000000000000000000006003611f5b6020860186614511565b50600101612045565b5082905060005b8181101561216c57368585838181106120f7576120f7614592565b905060200281019061210991906145a8565b905061212d61211b6020830183614511565b61212860208401846147d3565b6126ce565b9350612163337f00000000000000000000000000000000000000000000000000000000000000006004611f5b6020860186614511565b506001016120dc565b5060405133907ff48581d8a62b775b74f2fb67f1d5806a9a356fbcc598040ab3071d3e37af40c290600090a250505050505050505050565b606060006001600160a01b0384166001148015906121ca57506121c8868686613417565b155b156121f357604051637c84ecfb60e01b81526001600160a01b0385166004820152602401610633565b826000036122145760405163f725081760e01b815260040160405180910390fd5b826001600160401b0381111561222c5761222c6141d3565b604051908082528060200260200182016040528015612255578160200160208202803683370190505b506001600160a01b038086166000908152602089815260408083208a85168452909152812054929450911691505b6001600160a01b038216158015906122a557506001600160a01b038216600114155b80156122b057508381105b1561231557818382815181106122c8576122c8614592565b6001600160a01b039283166020918202929092018101919091529281166000908152888452604080822089841683529094529290922054909116908061230d8161482f565b915050612283565b6001600160a01b03821660011480159061232f5750600081115b1561235b5782612340600183614848565b8151811061235057612350614592565b602002602001015191505b8083525094509492505050565b60016000908152602083815260408083206001600160a01b03808616855292529091205416156123ab576040516329e42f3360e11b815260040160405180910390fd5b60016000818152602093845260408082206001600160a01b0394909416825292909352912080546001600160a01b0319169091179055565b6001600160a01b038116158061240257506001600160a01b0381166001145b1561242b57604051637c84ecfb60e01b81526001600160a01b0382166004820152602401610633565b6001600160a01b038181166000908152602085815260408083208685168452909152902054161561247a57604051631034f46960e21b81526001600160a01b0382166004820152602401610633565b60016000908152602084815260408083206001600160a01b039586168085528184528285208054968816808752988552838620918652908452919093208054949095166001600160a01b031994851617909455528154169091179055565b60608360016124e78282612e0f565b6124f3600133886123e3565b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929998505050505050505050565b60608360026125438282612e0f565b6124f3600233886123e3565b606083600361255e8282612e0f565b6000808061256e878901896148ac565b919450925090506001600160e01b031983166306d61fe760e41b14806125a457506001600160e01b03198316638a91b0e360e01b145b156125ce576040516379bd117b60e01b81526001600160e01b031984166004820152602401610633565b6125d9826000611a76565b80156125ee57506125ee82607f60f91b611a76565b1561260e57816040516376087dc160e01b815260040161063391906145fb565b6001600160e01b0319831660009081526003602090815260408083203384529091529020546001600160a01b031615612666576040516374420d1560e01b81526001600160e01b031984166004820152602401610633565b6001600160e01b03199092166000908152600360209081526040808320338452909152902080546001600160a01b038a166001600160a01b031960f89490941c600160a01b02939093166001600160a81b031990911617919091179055925050509392505050565b60608360046126dd8282612e0f565b600080806126ed8789018961491a565b9194509250905060008084600181111561270957612709614610565b14801561271e57506001600160e01b03198316155b156127945750336000908152600460205260409020546001600160a01b031680156127675760405163741cbe0360e01b81526001600160a01b0382166004820152602401610633565b33600090815260046020526040902080546001600160a01b0319166001600160a01b038c16179055612861565b60018460018111156127a8576127a8614610565b0361284857506001600160e01b0319821660009081526005602090815260408083203384529091529020546001600160a01b031680156128065760405163741cbe0360e01b81526001600160a01b0382166004820152602401610633565b6001600160e01b031983166000908152600560209081526040808320338452909152902080546001600160a01b0319166001600160a01b038c16179055612861565b604051635691922f60e01b815260040160405180910390fd5b5098975050505050505050565b606082358301602081810191359085810135860180820191903590604088013588019081019035848381146128b65760405163b4fa3fb360e01b815260040160405180910390fd5b60005b818110156129d85760008888838181106128d5576128d5614592565b905060200201359050600181036129145761290e8d8888858181106128fc576128fc614592565b9050602002810190611f2091906147d3565b506129cf565b600281036129445761290e8d88888581811061293257612932614592565b9050602002810190611ffa91906147d3565b600381036129745761290e8d88888581811061296257612962614592565b905060200281019061209191906147d3565b600481036129a45761290e8d88888581811061299257612992614592565b905060200281019061212891906147d3565b60405163484d218160e01b81526001600160a01b038e16600482015260248101829052604401610633565b506001016128b9565b5082828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929e9d5050505050505050505050505050565b60405163468721a760e01b81526000906001600160a01b0385169063468721a790612a5590869085908790600190600401614648565b6020604051808303816000875af1158015612a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9891906146ff565b90508061075c57604051632b3f6d1160e21b815260040160405180910390fd5b60606000612ac883850185614948565b92509050612ad9600133838861375c565b509392505050565b60606000612af183850185614948565b92509050612ad9600233838861375c565b60606000612b128385018561498d565b6001600160e01b03199091166000908152600360209081526040808320338452909152902080546001600160a01b031916905595945050505050565b6060600080612b5f8486018661491a565b945090925090506000826001811115612b7a57612b7a614610565b148015612b8f57506001600160e01b03198116155b15612bb65733600090815260046020526040902080546001600160a01b0319169055610c40565b6001826001811115612bca57612bca614610565b03612848576001600160e01b031981166000908152600560209081526040808320338452909152902080546001600160a01b0319169055610c40565b60608235830160208181019135908581013586018082019190359060408801358801908101903584838114612c4e5760405163b4fa3fb360e01b815260040160405180910390fd5b60005b818110156129d8576000888883818110612c6d57612c6d614592565b90506020020135905060018103612cb157612cab8d888885818110612c9457612c94614592565b9050602002810190612ca691906147d3565b612ab8565b50612d50565b60028103612ce657612cab8d888885818110612ccf57612ccf614592565b9050602002810190612ce191906147d3565b612ae1565b60038103612d1b57612cab8d888885818110612d0457612d04614592565b9050602002810190612d1691906147d3565b612b02565b600481036129a457612cab8d888885818110612d3957612d39614592565b9050602002810190612d4b91906147d3565b612b4e565b50600101612c51565b60405163468721a760e01b81526000906001600160a01b0385169063468721a790612d8f90869085908790600190600401614648565b6020604051808303816000875af1158015612dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd291906146ff565b90508061075c57604080516001600160a01b038616815260006020820152600080516020614c64833981519152910160405180910390a150505050565b336000908152602081905260409020546001600160a01b03168015612e955760405163529562a160e01b81523360048201526001600160a01b0384811660248301526044820184905282169063529562a19060640160006040518083038186803b158015612e7c57600080fd5b505afa158015612e90573d6000803e3d6000fd5b505050505b505050565b6060612ea7856000611a76565b1561309357612eba84600160f81b611a76565b15612edd5782358301602081019035612ed4338383613853565b925050506107b7565b612ee8846000611a76565b15612f9c57600080366000612efd87876132a9565b6040805160018082528183019092529498509296509094509250816020015b6060815260200190600190039081612f1c579050509450612f7533858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506119cd92505050565b85600081518110612f8857612f88614592565b6020026020010181905250505050506107b7565b612fae846001600160f81b0319611a76565b15613078576000612fc260148285876142fd565b612fcb91614327565b60601c9050366000612fe085601481896142fd565b604080516001808252818301909252929450909250816020015b6060815260200190600190039081612ffa579050509350613052338484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138cf92505050565b8460008151811061306557613065614592565b60200260200101819052505050506107b7565b83604051632e5bf3f960e21b815260040161063391906145fb565b6130a185600160f81b611a76565b15613227576130b484600160f81b611a76565b156130d957823583016020810190356130ce338383613970565b93506107b792505050565b6130e4846000611a76565b15613171576000803660006130f987876132a9565b6040805160018082528183019092529498509296509094509250816020015b6060815260200190600190039081613118579050509450612f7533858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a6692505050565b613183846001600160f81b0319611a76565b1561307857600061319760148285876142fd565b6131a091614327565b60601c90503660006131b585601481896142fd565b604080516001808252818301909252929450909250816020015b60608152602001906001900390816131cf579050509350613052338484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613b2692505050565b846040516308c3ee0360e11b815260040161063391906145fb565b612e95837f0000000000000000000000000000000000000000000000000000000000000000848460405160240161327a9291906149ab565b60408051601f198184030181529190526020810180516001600160e01b0316633f707e6b60e01b179052612a1f565b60008036816132bb60148287896142fd565b6132c491614327565b60601c93506132d76034601487896142fd565b6132e091614a5d565b92506132ef85603481896142fd565b949793965094505050565b612e95837f000000000000000000000000000000000000000000000000000000000000000084846040516024016133329291906149ab565b60408051601f198184030181529190526020810180516001600160e01b0316632864481160e11b179052612d59565b60405163468721a760e01b81526000906001600160a01b0386169063468721a790613396908790879087908790600401614648565b6020604051808303816000875af11580156133b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d991906146ff565b905080611bf557604080516001600160a01b038716815260006020820152600080516020614c64833981519152910160405180910390a15050505050565b600060016001600160a01b038316148015906107b75750506001600160a01b0390811660009081526020938452604080822093831682529290935291205416151590565b60008083600181111561347057613470614610565b14801561348557506001600160e01b03198216155b156134a55750336000908152600460205260409020546001600160a01b03165b60018360018111156134b9576134b9614610565b036106d957506001600160e01b03191660009081526005602090815260408083203384529091529020546001600160a01b0316919050565b6060600080368181816135086101008a018a6147d3565b909250905061351b6006600083856142fd565b61352491614a7b565b60d01c9550613537600c600683856142fd565b61354091614a7b565b60d01c945061355281600c81856142fd565b9350935050506000604051806101c001604052807fc03dfc11d8b10bf9cf703d558958c8c42777f785d998c62060d85a4f0ef6ea7f60001b81526020018960000160208101906135a29190614511565b6001600160a01b03168152602001896020013581526020018980604001906135ca91906147d3565b6040516135d8929190614ab1565b60405190819003902081526020016135f360608b018b6147d3565b604051613601929190614ab1565b604051809103902081526020016136178a613be6565b6001600160801b0316815260200161362e8a613bf6565b6001600160801b031681526020018960a00135815260200161364f8a613c0b565b6001600160801b031681526020016136668a613c1a565b6001600160801b0316815260200161368160e08b018b6147d3565b60405161368f929190614ab1565b6040805191829003909120825265ffffffffffff80891660208401528716908201526001600160a01b0389166060909101526101c08120909150601960f81b600160f81b6136db611968565b6040516001600160f81b03199384166020820152929091166021830152602282015260428101829052606201604051602081830303815290604052965050509295509295909350565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561374c57600061374f565b60015b60ff161717949350505050565b6001600160a01b038116158061377b57506001600160a01b0381166001145b156137a457604051637c84ecfb60e01b81526001600160a01b0383166004820152602401610633565b6001600160a01b0382811660009081526020868152604080832087851684529091529020548116908216146137f757604051637c84ecfb60e01b81526001600160a01b0382166004820152602401610633565b6001600160a01b039081166000908152602085815260408083209584168084528683528184208054968616855297835281842090845282529091208054939092166001600160a01b031993841617909155919091528154169055565b60606138bc847f0000000000000000000000000000000000000000000000000000000000000000858560405160240161388d9291906149ab565b60408051601f198184030181529190526020810180516001600160e01b0316636108557360e01b1790526138cf565b8060200190518101906107b79190614b70565b60606000846001600160a01b0316635229073f8560008660016040518563ffffffff1660e01b81526004016139079493929190614648565b6000604051808303816000875af1158015613926573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261394e919081019061468e565b9250905080612ad957604051632b3f6d1160e21b815260040160405180910390fd5b60608060006139dc867f000000000000000000000000000000000000000000000000000000000000000087876040516024016139ad9291906149ab565b60408051601f198184030181529190526020810180516001600160e01b0316639abb6e1760e01b179052613b26565b9050808060200190518101906139f29190614ba4565b8151919450925060005b81811015613a5b57848181518110613a1657613a16614592565b6020026020010151613a5357604080516001600160a01b038a16815260208101839052600080516020614c64833981519152910160405180910390a15b6001016139fc565b505050935093915050565b60606000856001600160a01b0316635229073f86868660006040518563ffffffff1660e01b8152600401613a9d9493929190614648565b6000604051808303816000875af1158015613abc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613ae4919081019061468e565b9250905080611a6d57604080516001600160a01b038816815260006020820152600080516020614c64833981519152910160405180910390a150949350505050565b60606000846001600160a01b0316635229073f8560008660016040518563ffffffff1660e01b8152600401613b5e9493929190614648565b6000604051808303816000875af1158015613b7d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613ba5919081019061468e565b9250905080612ad957604080516001600160a01b038716815260006020820152600080516020614c64833981519152910160405180910390a1509392505050565b60006106d9826080013560801c90565b60006001600160801b036080830135166106d9565b600060c082013560801c6106d9565b60006001600160801b0360c0830135166106d9565b6001600160a01b0381168114613c4457600080fd5b50565b803561196381613c2f565b60008083601f840112613c6457600080fd5b5081356001600160401b03811115613c7b57600080fd5b6020830191508360208285010111156105c557600080fd5b60008060008060608587031215613ca957600080fd5b843593506020850135613cbb81613c2f565b925060408501356001600160401b03811115613cd657600080fd5b613ce287828801613c52565b95989497509550505050565b600080600060408486031215613d0357600080fd5b8335925060208401356001600160401b03811115613d2057600080fd5b613d2c86828701613c52565b9497909650939450505050565b600080600060608486031215613d4e57600080fd5b83356001600160401b03811115613d6457600080fd5b84016101208187031215613d7757600080fd5b95602085013595506040909401359392505050565b60008083601f840112613d9e57600080fd5b5081356001600160401b03811115613db557600080fd5b6020830191508360208260051b85010111156105c557600080fd5b600060608284031215613de257600080fd5b50919050565b600080600080600080600080600060a08a8c031215613e0657600080fd5b89356001600160401b03811115613e1c57600080fd5b613e288c828d01613d8c565b909a5098505060208a01356001600160401b03811115613e4757600080fd5b613e538c828d01613d8c565b90985096505060408a01356001600160401b03811115613e7257600080fd5b613e7e8c828d01613d8c565b90965094505060608a01356001600160401b03811115613e9d57600080fd5b613ea98c828d01613d8c565b90945092505060808a01356001600160401b03811115613ec857600080fd5b613ed48c828d01613dd0565b9150509295985092959850929598565b60008060408385031215613ef757600080fd5b8235613f0281613c2f565b946020939093013593505050565b6040808252835190820181905260009060208501906060840190835b81811015613f535783516001600160a01b0316835260209384019390920191600101613f2c565b50506001600160a01b039490941660209390930192909252509092915050565b60008060208385031215613f8657600080fd5b82356001600160401b03811115613f9c57600080fd5b613fa885828601613d8c565b90969095509350505050565b60005b83811015613fcf578181015183820152602001613fb7565b50506000910152565b60008151808452613ff0816020860160208601613fb4565b601f01601f19169290920160200192915050565b602081526000610b2e6020830184613fd8565b6001600160e01b031981168114613c4457600080fd5b60006020828403121561403f57600080fd5b8135610b2e81614017565b60006020828403121561405c57600080fd5b5035919050565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156140bc57603f198786030184526140a7858351613fd8565b9450602093840193919091019060010161408b565b50929695505050505050565b600080604083850312156140db57600080fd5b82356140e681613c2f565b915060208301356140f681613c2f565b809150509250929050565b803560ff8116811461196357600080fd5b6000806000806060858703121561412857600080fd5b843561413381613c2f565b935060208501356001600160401b0381111561414e57600080fd5b61415a87828801613d8c565b909450925061416d905060408601614101565b905092959194509250565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b03851681528360208201526060604082015260006141c9606083018486614178565b9695505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614211576142116141d3565b604052919050565b60006001600160401b03821115614232576142326141d3565b50601f01601f191660200190565b600082601f83011261425157600080fd5b815161426461425f82614219565b6141e9565b81815284602083860101111561427957600080fd5b6107b7826020830160208701613fb4565b60006020828403121561429c57600080fd5b81516001600160401b038111156142b257600080fd5b6107b784828501614240565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b6000602082840312156142f657600080fd5b5051919050565b6000808585111561430d57600080fd5b8386111561431a57600080fd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561436d576bffffffffffffffffffffffff196bffffffffffffffffffffffff198560140360031b1b82161691505b5092915050565b84815260606020820152600061438d6060830186613fd8565b82810360408401526143a0818587614178565b979650505050505050565b6000602082840312156143bd57600080fd5b8151610b2e81614017565b6000808335601e198436030181126143df57600080fd5b83016020810192503590506001600160401b038111156143fe57600080fd5b8036038213156105c557600080fd5b6040815261442e6040820161442185613c47565b6001600160a01b03169052565b60208301356060820152600061444760408501856143c8565b610120608085015261445e61016085018284614178565b91505061446e60608601866143c8565b848303603f190160a0860152614485838284614178565b608088013560c08781019190915260a089013560e080890191909152908901356101008801529093506144bd925087019050866143c8565b848303603f19016101208601526144d5838284614178565b925050506144e76101008601866143c8565b848303603f19016101408601526144ff838284614178565b93505050508260208301529392505050565b60006020828403121561452357600080fd5b8135610b2e81613c2f565b6000808335601e1984360301811261454557600080fd5b8301803591506001600160401b0382111561455f57600080fd5b6020019150600581901b36038213156105c557600080fd5b60006020828403121561458957600080fd5b610b2e82614101565b634e487b7160e01b600052603260045260246000fd5b60008235603e198336030181126145be57600080fd5b9190910192915050565b8381526001600160a01b03831660208201526060604082018190526000906145f290830184613fd8565b95945050505050565b6001600160f81b031991909116815260200190565b634e487b7160e01b600052602160045260246000fd5b6002811061464457634e487b7160e01b600052602160045260246000fd5b9052565b60018060a01b038516815283602082015260806040820152600061466f6080830185613fd8565b90506145f26060830184614626565b8051801515811461196357600080fd5b600080604083850312156146a157600080fd5b6146aa8361467e565b915060208301516001600160401b038111156146c557600080fd5b6146d185828601614240565b9150509250929050565b6001600160a01b03831681526040602082018190526000906107b790830184613fd8565b60006020828403121561471157600080fd5b610b2e8261467e565b80356002811061196357600080fd5b6000806040838503121561473c57600080fd5b6147458361471a565b915060208301356140f681614017565b8281526000825161476d816020850160208701613fb4565b919091016020019392505050565b60ff84168152604060208201819052810182905260008360608301825b858110156147c85782356147ab81613c2f565b6001600160a01b0316825260209283019290910190600101614798565b509695505050505050565b6000808335601e198436030181126147ea57600080fd5b8301803591506001600160401b0382111561480457600080fd5b6020019150368190038213156105c557600080fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161484157614841614819565b5060010190565b818103818111156106d9576106d9614819565b600082601f83011261486c57600080fd5b813561487a61425f82614219565b81815284602083860101111561488f57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000606084860312156148c157600080fd5b83356148cc81614017565b925060208401356001600160f81b0319811681146148e957600080fd5b915060408401356001600160401b0381111561490457600080fd5b6149108682870161485b565b9150509250925092565b60008060006060848603121561492f57600080fd5b6149388461471a565b925060208401356148e981614017565b6000806040838503121561495b57600080fd5b823561496681613c2f565b915060208301356001600160401b0381111561498157600080fd5b6146d18582860161485b565b600080604083850312156149a057600080fd5b823561496681614017565b6020808252810182905260006040600584901b830181019083018583605e1936839003015b87821015614a5057868503603f1901845282358181126149ef57600080fd5b890180356149fc81613c2f565b6001600160a01b0316865260208181013590870152614a1e60408201826143c8565b915060606040880152614a35606088018383614178565b965050506020830192506020840193506001820191506149d0565b5092979650505050505050565b803560208310156106d957600019602084900360031b1b1692915050565b80356001600160d01b0319811690600684101561436d576001600160d01b031960069490940360031b84901b1690921692915050565b8183823760009101908152919050565b60006001600160401b03821115614ada57614ada6141d3565b5060051b60200190565b600082601f830112614af557600080fd5b8151614b0361425f82614ac1565b8082825260208201915060208360051b860101925085831115614b2557600080fd5b602085015b83811015614b665780516001600160401b03811115614b4857600080fd5b614b57886020838a0101614240565b84525060209283019201614b2a565b5095945050505050565b600060208284031215614b8257600080fd5b81516001600160401b03811115614b9857600080fd5b6107b784828501614ae4565b60008060408385031215614bb757600080fd5b82516001600160401b03811115614bcd57600080fd5b8301601f81018513614bde57600080fd5b8051614bec61425f82614ac1565b8082825260208201915060208360051b850101925087831115614c0e57600080fd5b6020840193505b82841015614c3757614c268461467e565b825260209384019390910190614c15565b8095505050505060208301516001600160401b03811115614c5757600080fd5b6146d185828601614ae456feb8bc84bd77f5eb08210b8eb20fd63b3ec6a7992d277ab94663bae0e066f792aca26469706673582212200d02bd25771a1d64ddd9e60d84bf6d2381636a59cdc715f1f0a2c7ae4cc5390864736f6c634300081a00336080604052348015600f57600080fd5b506109c28061001f6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80636a2216571161005b5780636a221657146100d357806378272525146100e65780639517e29f146100f95780639abb6e171461010c57600080fd5b80633f707e6b1461008257806350c890221461009757806361085573146100aa575b600080fd5b6100956100903660046105ba565b61012d565b005b6100956100a53660046105ba565b610197565b6100bd6100b83660046105ba565b6101fc565b6040516100ca91906106c4565b60405180910390f35b6100956100e1366004610710565b6102be565b6100956100f43660046107da565b6102e1565b6100956101073660046107da565b61038a565b61011f61011a3660046105ba565b610429565b6040516100ca929190610864565b8060005b81811015610191573684848381811061014c5761014c6108be565b905060200281019061015e91906108d4565b905061018761017060208301836108f4565b6020830135610182604085018561090f565b610553565b5050600101610131565b50505050565b8060005b8181101561019157368484838181106101b6576101b66108be565b90506020028101906101c891906108d4565b90506101f16101da60208301836108f4565b60208301356101ec604085018561090f565b610589565b50505060010161019b565b6060818067ffffffffffffffff811115610218576102186106fa565b60405190808252806020026020018201604052801561024b57816020015b60608152602001906001900390816102365790505b50915060005b818110156102b6573685858381811061026c5761026c6108be565b905060200281019061027e91906108d4565b905061029061017060208301836108f4565b8483815181106102a2576102a26108be565b602090810291909101015250600101610251565b505092915050565b604051600080835160208501865afa3d6000833e80156102dc573d82f35b503d81fd5b604051638a91b0e360e01b81526001600160a01b03841690638a91b0e39061030f908590859060040161095d565b600060405180830381600087803b15801561032957600080fd5b505af115801561033d573d6000803e3d6000fd5b5050604080518781526001600160a01b03871660208201527f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e93500190505b60405180910390a150505050565b6040516306d61fe760e41b81526001600160a01b03841690636d61fe70906103b8908590859060040161095d565b600060405180830381600087803b1580156103d257600080fd5b505af11580156103e6573d6000803e3d6000fd5b5050604080518781526001600160a01b03871660208201527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123935001905061037c565b606080828067ffffffffffffffff811115610446576104466106fa565b60405190808252806020026020018201604052801561047957816020015b60608152602001906001900390816104645790505b5091508067ffffffffffffffff811115610495576104956106fa565b6040519080825280602002602001820160405280156104be578160200160208202803683370190505b50925060005b8181101561054a57368686838181106104df576104df6108be565b90506020028101906104f191906108d4565b90506105036101da60208301836108f4565b868481518110610515576105156108be565b6020026020010186858151811061052e5761052e6108be565b60209081029190910101919091529015159052506001016104c4565b50509250929050565b60405181838237600038838387895af1610570573d6000823e3d81fd5b3d8152602081013d6000823e3d01604052949350505050565b604051600090828482376000388483888a5af191503d8152602081013d6000823e3d81016040525094509492505050565b600080602083850312156105cd57600080fd5b823567ffffffffffffffff8111156105e457600080fd5b8301601f810185136105f557600080fd5b803567ffffffffffffffff81111561060c57600080fd5b8560208260051b840101111561062157600080fd5b6020919091019590945092505050565b600082825180855260208501945060208160051b8301016020850160005b838110156106b857848303601f190188528151805180855260005b818110156106865760208184018101518783018201520161066a565b506000602082870101526020601f19601f8301168601019450505060208201915060208801975060018101905061064f565b50909695505050505050565b6020815260006106d76020830184610631565b9392505050565b80356001600160a01b03811681146106f557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072357600080fd5b61072c836106de565b9150602083013567ffffffffffffffff81111561074857600080fd5b8301601f8101851361075957600080fd5b803567ffffffffffffffff811115610773576107736106fa565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156107a2576107a26106fa565b6040528181528282016020018710156107ba57600080fd5b816020840160208301376000602083830101528093505050509250929050565b600080600080606085870312156107f057600080fd5b84359350610800602086016106de565b9250604085013567ffffffffffffffff81111561081c57600080fd5b8501601f8101871361082d57600080fd5b803567ffffffffffffffff81111561084457600080fd5b87602082840101111561085657600080fd5b949793965060200194505050565b6040808252835190820181905260009060208501906060840190835b818110156108a05783511515835260209384019390920191600101610880565b505083810360208501526108b48186610631565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b60008235605e198336030181126108ea57600080fd5b9190910192915050565b60006020828403121561090657600080fd5b6106d7826106de565b6000808335601e1984360301811261092657600080fd5b83018035915067ffffffffffffffff82111561094157600080fd5b60200191503681900382131561095657600080fd5b9250929050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122070a59ccb068447caf8f890604a59f833f8725c3e3d150ae8a83f15caaa17700e64736f6c634300081a0033" + /* ========= V06 CORE ========= */ // Will deploy entryPoint to 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 @@ -140,3 +149,6 @@ export const TRUST_DIAMOND_LOUPE_FACET_CREATE_CALL: Hex = export const TRUST_DEFAULT_FALLBACK_HANDLER: Hex = "0x00000000000000000000000000000000000000000000000000000000000000006080604052604051620020183803806200201883398101604081905262000026916200156b565b60408051600480825260a08201909252600091816020015b604080516060808201835260008083526020830152918101919091528152602001906001900390816200003e5750506040805160018082528183019092529192506000919060208083019080368337019050509050631f931c1c60e01b81600081518110620000b157620000b1620015c8565b6001600160e01b03199290921660209283029190910182015260408051600580825260c08201909252600092909190820160a08036833701905050905063b61d27f660e01b816000815181106200010c576200010c620015c8565b6001600160e01b03199092166020928302919091019091015280516323f0ed1560e11b9082906001908110620001465762000146620015c8565b6001600160e01b0319909216602092830291909101909101528051633a871cdd60e01b9082906002908110620001805762000180620015c8565b6001600160e01b0319909216602092830291909101909101528051631a10fa5160e31b9082906003908110620001ba57620001ba620015c8565b6001600160e01b031990921660209283029190910190910152805163586b48ff60e11b9082906004908110620001f457620001f4620015c8565b6001600160e01b03199290921660209283029190910182015260408051600580825260c08201909252600092909190820160a08036833701905050905063150b7a0260e01b816000815181106200024f576200024f620015c8565b6001600160e01b031990921660209283029190910190910152805163f23a6e6160e01b9082906001908110620002895762000289620015c8565b6001600160e01b031990921660209283029190910190910152805163bc197c8160e01b9082906002908110620002c357620002c3620015c8565b6001600160e01b03199092166020928302919091019091015280516223de2960e01b9082906003908110620002fc57620002fc620015c8565b6001600160e01b0319909216602092830291909101909101528051635260769b60e11b9082906004908110620003365762000336620015c8565b6001600160e01b0319929092166020928302919091018201526040805160098082526101408201909252600092909190820161012080368337019050509050637a0ed62760e01b81600081518110620003935762000393620015c8565b6001600160e01b03199092166020928302919091019091015280516356fe50af60e11b9082906001908110620003cd57620003cd620015c8565b6001600160e01b03199092166020928302919091019091015280516314bbdacb60e21b9082906002908110620004075762000407620015c8565b6001600160e01b03199092166020928302919091019091015280516366ffd66360e11b9082906003908110620004415762000441620015c8565b6001600160e01b03199092166020928302919091019091015280516301ffc9a760e01b90829060049081106200047b576200047b620015c8565b6001600160e01b031990921660209283029190910190910152805163f9796ccf60e01b9082906005908110620004b557620004b5620015c8565b6001600160e01b031990921660209283029190910190910152805162d2a81160e11b9082906006908110620004ee57620004ee620015c8565b6001600160e01b031990921660209283029190910190910152805163d42139a960e01b9082906007908110620005285762000528620015c8565b6001600160e01b03199092166020928302919091019091015280516371d17b7f60e11b9082906008908110620005625762000562620015c8565b6001600160e01b031990921660209283029190910182015260408051606081019091526001600160a01b038b168152908101600081526020018581525085600081518110620005b557620005b5620015c8565b60200260200101819052506040518060600160405280896001600160a01b0316815260200160006002811115620005f057620005f0620015de565b815260200184815250856001815181106200060f576200060f620015c8565b60200260200101819052506040518060600160405280886001600160a01b03168152602001600060028111156200064a576200064a620015de565b81526020018381525085600281518110620006695762000669620015c8565b60200260200101819052506040518060600160405280876001600160a01b0316815260200160006002811115620006a457620006a4620015de565b81526020018281525085600381518110620006c357620006c3620015c8565b6020026020010181905250620006f1856000604051806020016040528060008152506200070060201b60201c565b5050505050505050506200184c565b60005b83518110156200090c576000848281518110620007245762000724620015c8565b602002602001015160200151905060006002811115620007485762000748620015de565b8160028111156200075d576200075d620015de565b03620007bb57620007b58583815181106200077c576200077c620015c8565b6020026020010151600001518684815181106200079d576200079d620015c8565b6020026020010151604001516200095b60201b60201c565b620008f6565b6001816002811115620007d257620007d2620015de565b036200082a57620007b5858381518110620007f157620007f1620015c8565b602002602001015160000151868481518110620008125762000812620015c8565b60200260200101516040015162000bf760201b60201c565b6002816002811115620008415762000841620015de565b036200089957620007b5858381518110620008605762000860620015c8565b602002602001015160000151868481518110620008815762000881620015c8565b60200260200101516040015162000ea160201b60201c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084015b60405180910390fd5b508062000903816200160a565b91505062000703565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405162000942939291906200167a565b60405180910390a162000956828262001005565b505050565b805180620009af5760405162461bcd60e51b815260206004820152602b602482015260008051602062001ff883398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620008ed565b60008051602062001f8c8339815191526001600160a01b03841662000a2c5760405162461bcd60e51b815260206004820152602c60248201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260448201526b65206164647265737328302960a01b6064820152608401620008ed565b6001600160a01b0384166000908152600182016020526040812054906001600160601b038216900362000a655762000a658286620010dd565b60005b8381101562000bef57600085828151811062000a885762000a88620015c8565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b0316801562000b305760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401620008ed565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558d168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b0319161790558362000bd48162001781565b9450505050808062000be6906200160a565b91505062000a68565b505050505050565b80518062000c4b5760405162461bcd60e51b815260206004820152602b602482015260008051602062001ff883398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620008ed565b60008051602062001f8c8339815191526001600160a01b03841662000ccc5760405162461bcd60e51b815260206004820152603060248201527f4c69624469616d6f6e644375743a205265706c6163652066616365742063616e60448201526f2774206265206164647265737328302960801b6064820152608401620008ed565b6001600160a01b0384166000908152600182016020526040812054906001600160601b038216900362000d055762000d058286620010dd565b60005b8381101562000bef57600085828151811062000d285762000d28620015c8565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b03908116908816810362000dd55760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d6520666163657400000000000000000000006064820152608401620008ed565b62000de28582846200114a565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558d168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b0319161790558362000e868162001781565b9450505050808062000e98906200160a565b91505062000d08565b80518062000ef55760405162461bcd60e51b815260206004820152602b602482015260008051602062001ff883398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620008ed565b60008051602062001f8c8339815191526001600160a01b0384161562000f845760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401620008ed565b60005b8281101562000ffe57600084828151811062000fa75762000fa7620015c8565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b031662000fe68482846200114a565b5050808062000ff5906200160a565b91505062000f87565b5050505050565b6001600160a01b03821662001018575050565b6200103d8260405180606001604052806028815260200162001fac602891396200152a565b600080836001600160a01b0316836040516200105a9190620017b2565b600060405180830381855af49150503d806000811462001097576040519150601f19603f3d011682016040523d82523d6000602084013e6200109c565b606091505b509150915081620010d757805115620010b85780518082602001fd5b838360405163192105d760e01b8152600401620008ed929190620017d0565b50505050565b620011028160405180606001604052806024815260200162001fd4602491396200152a565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160a01b038216620011c85760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401620008ed565b306001600160a01b03831603620012395760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401620008ed565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b031692916200128a91620017fe565b905080821462001383576001600160a01b03841660009081526001860160205260408120805483908110620012c357620012c3620015c8565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b925082919085908110620013175762001317620015c8565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b03841660009081526001860160205260409020805480620013af57620013af6200181a565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319851682528690526040812081905581900362000ffe5760028501546000906200141590600190620017fe565b6001600160a01b0386166000908152600180890160205260409091200154909150808214620014cb576000876002018381548110620014585762001458620015c8565b6000918252602090912001546002890180546001600160a01b0390921692508291849081106200148c576200148c620015c8565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b86600201805480620014e157620014e16200181a565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b8181620010d75760405162461bcd60e51b8152600401620008ed919062001830565b80516001600160a01b03811681146200156657600080fd5b919050565b600080600080608085870312156200158257600080fd5b6200158d856200154e565b93506200159d602086016200154e565b9250620015ad604086016200154e565b9150620015bd606086016200154e565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016200161f576200161f620015f4565b5060010190565b60005b838110156200164357818101518382015260200162001629565b50506000910152565b600081518084526200166681602086016020860162001626565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b848110156200174f57898403607f19018652815180516001600160a01b03168552838101518986019060038110620016eb57634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015620017395783516001600160e01b03191682529286019260019290920191908601906200170d565b50978501979550505090820190600101620016a3565b50506001600160a01b038a169088015286810360408801526200177381896200164c565b9a9950505050505050505050565b60006001600160601b038281166002600160601b03198101620017a857620017a8620015f4565b6001019392505050565b60008251620017c681846020870162001626565b9190910192915050565b6001600160a01b0383168152604060208201819052600090620017f6908301846200164c565b949350505050565b81810381811115620018145762001814620015f4565b92915050565b634e487b7160e01b600052603160045260246000fd5b6020815260006200184560208301846200164c565b9392505050565b610730806200185c6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806352ef6b2c146100515780637a0ed6271461006f578063adfca15e14610084578063cdffacc6146100a4575b600080fd5b610059610140565b60405161006691906104ab565b60405180910390f35b6100776101d1565b6040516100669190610562565b61009761009236600461060a565b6103d1565b6040516100669190610647565b61011b6100b236600461065a565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081527f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610066565b60607f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f6002018054806020026020016040519081016040528092919081815260200182805480156101c757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161019c575b5050505050905090565b7f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd4921546060907f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f908067ffffffffffffffff8111156102315761023161069c565b60405190808252806020026020018201604052801561027757816020015b60408051808201909152600081526060602082015281526020019060019003908161024f5790505b50925060005b818110156103cb57600083600201828154811061029c5761029c6106cb565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050808583815181106102dc576102dc6106cb565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff928316905290821660009081526001860182526040908190208054825181850281018501909352808352919290919083018282801561039d57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161034a5790505b50505050508583815181106103b4576103b46106cb565b60209081029190910181015101525060010161027d565b50505090565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd4920602090815260409182902080548351818402810184019094528084526060939283018282801561049f57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161044c5790505b50505050509050919050565b6020808252825182820181905260009190848201906040850190845b818110156104f957835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016104c7565b50909695505050505050565b600081518084526020808501945080840160005b838110156105575781517fffffffff000000000000000000000000000000000000000000000000000000001687529582019590820190600101610519565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156105fc578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805173ffffffffffffffffffffffffffffffffffffffff1684528701518784018790526105e987850182610505565b9588019593505090860190600101610589565b509098975050505050505050565b60006020828403121561061c57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461064057600080fd5b9392505050565b6020815260006106406020830184610505565b60006020828403121561066c57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461064057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea264697066735822122024a872696a5ad50024326567061c50adea63ff0d49edf0ac60339459d33d571664736f6c63430008150033183cde5d4f6bb7b445b8fc2f7f15d0fd1d162275aded24183babbffee7cd491f4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f64654c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e20660000000000000000000000000b9504140771c3688ff041917192277d2f52e1e0000000000000000000000000fde53272dcd7938d16e031a6989753c3217283320000000000000000000000003143e1c0af0cdc153423863923cf4e3818e34daa000000000000000000000000ce36b85d12d81cd619c745c7717f3396e184ac7c" + +export const ERC_7579_TEST_MODULE_CREATECALL = + "0x00000000000000000000000000000000000000000000000000000000000000006080604052348015600f57600080fd5b50610f6a8061001f6000396000f3fe6080604052600436106100a75760003560e01c8063d26cdce311610064578063d26cdce3146101c1578063d60b347f146101d4578063e508600314610204578063ecd0596114610217578063fbe5ce0a14610238578063fd8b84b11461025857600080fd5b806306fdde03146100ac57806354fd4d50146100f65780636d61fe70146101245780637065cb48146101465780638a91b0e314610166578063ccfdec8c14610186575b600080fd5b3480156100b857600080fd5b5060408051808201909152600f81526e27bbb730b13632a2bc32b1baba37b960891b60208201525b6040516100ed9190610aca565b60405180910390f35b34801561010257600080fd5b506040805180820190915260058152640312e302e360dc1b60208201526100e0565b34801561013057600080fd5b5061014461013f366004610b46565b610285565b005b34801561015257600080fd5b50610144610161366004610ba4565b610311565b34801561017257600080fd5b50610144610181366004610b46565b6103c9565b34801561019257600080fd5b506101b36101a1366004610ba4565b60016020526000908152604090205481565b6040519081526020016100ed565b6101446101cf366004610bbf565b6103f5565b3480156101e057600080fd5b506101f46101ef366004610ba4565b6104b8565b60405190151581526020016100ed565b610144610212366004610bbf565b6104e8565b34801561022357600080fd5b506101f4610232366004610c12565b60021490565b34801561024457600080fd5b50610144610253366004610c2b565b61053e565b34801561026457600080fd5b50610278610273366004610ba4565b610573565b6040516100ed9190610c5e565b3360006102956014828587610cab565b61029e91610cd5565b60601c90506102cf600080846001600160a01b03166001600160a01b031681526020019081526020016000206105aa565b6001600160a01b03821660009081526020819052604090206102f19082610607565b506001600160a01b03166000908152600160208190526040909120555050565b3361031b816104b8565b6103485760405163f91bd6f160e01b81526001600160a01b03821660048201526024015b60405180910390fd5b6001600160a01b03821661037a5760405163b20f76e360e01b81526001600160a01b038316600482015260240161033f565b6001600160a01b038116600090815260208190526040902061039c9083610607565b6001600160a01b03811660009081526001602052604081208054916103c083610d20565b91905055505050565b3360009081526020819052604090206103e1906106dd565b505033600090815260016020526040812055565b6001600160a01b03831660009081526020819052604090206104179033610758565b61043457604051631a27eac360e11b815260040160405180910390fd5b826001600160a01b031663d691c96461044b610794565b84846040518463ffffffff1660e01b815260040161046b93929190610d39565b6000604051808303816000875af115801561048a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104b29190810190610db6565b50505050565b6001600160a01b038181166000908152602081815260408083206001845290915281205490911615155b92915050565b6001600160a01b038316600090815260208190526040902061050a9033610758565b61052757604051631a27eac360e11b815260040160405180910390fd5b826001600160a01b031663d691c96461044b6107a7565b3360009081526020819052604090206105589083836107b9565b3360009081526001602052604081208054916103c083610ecd565b6001600160a01b038116600090815260016020818152604080842054918490529092206060926105a3929061088e565b5092915050565b60016000908152602082905260409020546001600160a01b0316156105e2576040516329e42f3360e11b815260040160405180910390fd5b60016000818152602092909252604090912080546001600160a01b0319169091179055565b6001600160a01b038116158061062657506001600160a01b0381166001145b1561064f57604051637c84ecfb60e01b81526001600160a01b038216600482015260240161033f565b6001600160a01b03818116600090815260208490526040902054161561069357604051631034f46960e21b81526001600160a01b038216600482015260240161033f565b60016000818152602093909352604080842080546001600160a01b039485168087529286208054959091166001600160a01b03199586161790559190935280549091169091179055565b60016000908152602082905260409020546001600160a01b03165b6001600160a01b03811615610736576001600160a01b03908116600090815260208390526040902080546001600160a01b03198116909155166106f8565b50600160009081526020919091526040902080546001600160a01b0319169055565b600060016001600160a01b0383161480159061078d57506001600160a01b038281166000908152602085905260409020541615155b9392505050565b60006107a281808080610a3b565b905090565b60006107a2600160f81b828080610a3b565b6001600160a01b03811615806107d857506001600160a01b0381166001145b1561080157604051637c84ecfb60e01b81526001600160a01b038316600482015260240161033f565b6001600160a01b0382811660009081526020859052604090205481169082161461084957604051637c84ecfb60e01b81526001600160a01b038216600482015260240161033f565b6001600160a01b0390811660008181526020949094526040808520805494841686529085208054949093166001600160a01b0319948516179092559092528154169055565b606060006001600160a01b0384166001148015906108b357506108b18585610758565b155b156108dc57604051637c84ecfb60e01b81526001600160a01b038516600482015260240161033f565b826000036108fd5760405163f725081760e01b815260040160405180910390fd5b8267ffffffffffffffff81111561091657610916610d6f565b60405190808252806020026020018201604052801561093f578160200160208202803683370190505b506001600160a01b03808616600090815260208890526040812054929450911691505b6001600160a01b0382161580159061098457506001600160a01b038216600114155b801561098f57508381105b156109e957818382815181106109a7576109a7610ee4565b6001600160a01b0392831660209182029290920181019190915292811660009081529287905260409092205490911690806109e181610d20565b915050610962565b6001600160a01b038216600114801590610a035750600081115b15610a2f5782610a14600183610efa565b81518110610a2457610a24610ee4565b602002602001015191505b80835250935093915050565b604080516001600160f81b03198087166020830152851660218201526000602282018190526001600160e01b03198516602683015269ffffffffffffffffffff198416602a8301529101604051602081830303815290604052610a9d90610f0d565b95945050505050565b60005b83811015610ac1578181015183820152602001610aa9565b50506000910152565b6020815260008251806020840152610ae9816040850160208701610aa6565b601f01601f19169190910160400192915050565b60008083601f840112610b0f57600080fd5b50813567ffffffffffffffff811115610b2757600080fd5b602083019150836020828501011115610b3f57600080fd5b9250929050565b60008060208385031215610b5957600080fd5b823567ffffffffffffffff811115610b7057600080fd5b610b7c85828601610afd565b90969095509350505050565b80356001600160a01b0381168114610b9f57600080fd5b919050565b600060208284031215610bb657600080fd5b61078d82610b88565b600080600060408486031215610bd457600080fd5b610bdd84610b88565b9250602084013567ffffffffffffffff811115610bf957600080fd5b610c0586828701610afd565b9497909650939450505050565b600060208284031215610c2457600080fd5b5035919050565b60008060408385031215610c3e57600080fd5b610c4783610b88565b9150610c5560208401610b88565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015610c9f5783516001600160a01b031683529284019291840191600101610c7a565b50909695505050505050565b60008085851115610cbb57600080fd5b83861115610cc857600080fd5b5050820193919092039150565b6bffffffffffffffffffffffff198135818116916014851015610d025780818660140360031b1b83161692505b505092915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d3257610d32610d0a565b5060010190565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610dae57610dae610d6f565b604052919050565b60006020808385031215610dc957600080fd5b825167ffffffffffffffff80821115610de157600080fd5b8185019150601f86601f840112610df757600080fd5b825182811115610e0957610e09610d6f565b8060051b610e18868201610d85565b918252848101860191868101908a841115610e3257600080fd5b87870192505b83831015610ebf57825186811115610e505760008081fd5b8701603f81018c13610e625760008081fd5b88810151604088821115610e7857610e78610d6f565b610e89828901601f19168c01610d85565b8281528e82848601011115610e9e5760008081fd5b610ead838d8301848701610aa6565b85525050509187019190870190610e38565b9a9950505050505050505050565b600081610edc57610edc610d0a565b506000190190565b634e487b7160e01b600052603260045260246000fd5b818103818111156104e2576104e2610d0a565b80516020808301519190811015610f2e576000198160200360031b1b821691505b5091905056fea2646970667358221220c65136fce0b201208eef061080f14f2bd4c40a5b6bc536237b6b4ff59f86c2aa64736f6c63430008190033" diff --git a/packages/permissionless-test/mock-aa-infra/alto/index.ts b/packages/permissionless-test/mock-aa-infra/alto/index.ts index 8f60913a..4d3e7265 100644 --- a/packages/permissionless-test/mock-aa-infra/alto/index.ts +++ b/packages/permissionless-test/mock-aa-infra/alto/index.ts @@ -19,6 +19,7 @@ import { ENTRY_POINT_SIMULATIONS_CREATECALL, ENTRY_POINT_V06_CREATECALL, ENTRY_POINT_V07_CREATECALL, + ERC_7579_TEST_MODULE_CREATECALL, KERNEL_V06_ACCOUNT_V2_2_LOGIC_CREATECALL, KERNEL_V06_ECDSA_VALIDATOR_V2_2_CREATECALL, KERNEL_V06_FACTORY_CREATECALL, @@ -27,6 +28,9 @@ import { KERNEL_V07_FACTORY_CREATECALL, KERNEL_V07_META_FACTORY_CREATECALL, LIGHT_ACCOUNT_FACTORY_V110_CREATECALL, + SAFE_7579_LAUNCHPAD_CREATECALL, + SAFE_7579_MODULE_CREATECALL, + SAFE_7579_REGISTRY_CREATECALL, SAFE_MULTI_SEND_CALL_ONLY_CREATECALL, SAFE_MULTI_SEND_CREATECALL, SAFE_PROXY_FACTORY_CREATECALL, @@ -137,6 +141,24 @@ export const setupContracts = async (rpc: string) => { gas: 15_000_000n, nonce: nonce++ }), + walletClient.sendTransaction({ + to: DETERMINISTIC_DEPLOYER, + data: SAFE_7579_MODULE_CREATECALL, + gas: 15_000_000n, + nonce: nonce++ + }), + walletClient.sendTransaction({ + to: DETERMINISTIC_DEPLOYER, + data: SAFE_7579_REGISTRY_CREATECALL, + gas: 15_000_000n, + nonce: nonce++ + }), + walletClient.sendTransaction({ + to: DETERMINISTIC_DEPLOYER, + data: SAFE_7579_LAUNCHPAD_CREATECALL, + gas: 15_000_000n, + nonce: nonce++ + }), walletClient.sendTransaction({ to: DETERMINISTIC_DEPLOYER, data: SAFE_V07_MODULE_CREATECALL, @@ -232,6 +254,12 @@ export const setupContracts = async (rpc: string) => { data: TRUST_DEFAULT_FALLBACK_HANDLER, gas: 15_000_000n, nonce: nonce++ + }), + walletClient.sendTransaction({ + to: DETERMINISTIC_DEPLOYER, + data: ERC_7579_TEST_MODULE_CREATECALL, + gas: 15_000_000n, + nonce: nonce++ }) ]) @@ -374,6 +402,9 @@ export const setupContracts = async (rpc: string) => { "0x41675C099F32341bf84BFc5382aF534df5C7461a", // Safe Singleton "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526", // Safe Multi Send "0x9641d764fc13c8B624c04430C7356C1C7C8102e2", // Safe Multi Send Call Only + "0x3Fdb5BC686e861480ef99A6E3FaAe03c0b9F32e2", // Safe 7579 module + "0xEBe001b3D534B9B6E2500FB78E67a1A137f561CE", // Safe 7579 launchpad + "0x25A4b2F363678E13A0A5DB79b712dE00347a593E", // Safe 7579 Registry "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", // EntryPoint V0.6 "0x9406Cc6185a346906296840746125a0E44976454", // Simple Account Factory V0.6 "0x0000001c5b32F37F5beA87BDD5374eB2aC54eA8e", // Biconomy ECDSA Ownership Registry Module @@ -395,6 +426,7 @@ export const setupContracts = async (rpc: string) => { "0x0B9504140771C3688Ff041917192277D2f52E1e0", // Trust DiamondCutFacet "0x3143E1C0Af0Cdc153423863923Cf4e3818e34Daa", // Trust TokenReceiverFacet "0xCe36b85d12D81cd619C745c7717f3396E184Ac7C", // Trust DiamondLoupeFacet - "0x2e7f1dAe1F3799d20f5c31bEFdc7A620f664728D" // Trust DefaultFallbackHandler + "0x2e7f1dAe1F3799d20f5c31bEFdc7A620f664728D", // Trust DefaultFallbackHandler + "0xc98B026383885F41d9a995f85FC480E9bb8bB891" // ERC7579 Test Module ]) } diff --git a/packages/permissionless-test/src/utils.ts b/packages/permissionless-test/src/utils.ts index 15cb1ab0..4c125a88 100644 --- a/packages/permissionless-test/src/utils.ts +++ b/packages/permissionless-test/src/utils.ts @@ -9,6 +9,7 @@ import { createClient, createPublicClient, createWalletClient, + getAddress, parseEther } from "viem" import { @@ -16,10 +17,11 @@ import { mnemonicToAccount, privateKeyToAccount } from "viem/accounts" -import { foundry } from "viem/chains" +import { foundry, sepolia } from "viem/chains" import { type BundlerClient, ENTRYPOINT_ADDRESS_V06, + ENTRYPOINT_ADDRESS_V07, type SmartAccountClient, createBundlerClient, createSmartAccountClient @@ -27,6 +29,11 @@ import { import { type SafeSmartAccount, type SmartAccount, + privateKeyToBiconomySmartAccount, + privateKeyToLightSmartAccount, + privateKeyToSafeSmartAccount, + privateKeyToSimpleSmartAccount, + privateKeyToTrustSmartAccount, signerToBiconomySmartAccount, signerToEcdsaKernelSmartAccount, signerToLightSmartAccount, @@ -44,6 +51,7 @@ import { import { paymasterActionsEip7677 } from "../../permissionless/experimental" import type { ENTRYPOINT_ADDRESS_V06_TYPE, + ENTRYPOINT_ADDRESS_V07_TYPE, EntryPoint } from "../../permissionless/types" import type { AAParamType, ExistingSignerParamType } from "./types" @@ -130,9 +138,15 @@ export const getPimlicoBundlerClient = ({ }) export const getPublicClient = (anvilRpc: string) => { + const transport = http(anvilRpc, { + onFetchRequest: async (request) => { + // console.log("fetching", await request.json()) + } + }) + return createPublicClient({ chain: foundry, - transport: http(anvilRpc), + transport: transport, pollingInterval: 100 }) } @@ -175,19 +189,21 @@ export const getSimpleAccountClient = async ({ paymasterClient, anvilRpc, altoRpc, - privateKey = generatePrivateKey() + privateKey }: AAParamType): Promise< SmartAccountClient> > => { const publicClient = getPublicClient(anvilRpc) - const smartAccount = await signerToSimpleSmartAccount( - publicClient, - { - entryPoint, - signer: privateKeyToAccount(privateKey) - } - ) + const smartAccount = privateKey + ? await privateKeyToSimpleSmartAccount(publicClient, { + entryPoint, + privateKey + }) + : await signerToSimpleSmartAccount(publicClient, { + entryPoint, + signer: privateKeyToAccount(generatePrivateKey()) + }) return createSmartAccountClient({ chain: foundry, @@ -207,16 +223,22 @@ export const getLightAccountClient = async ({ paymasterClient, anvilRpc, altoRpc, - privateKey = generatePrivateKey() + privateKey }: AAParamType): Promise< SmartAccountClient> > => { const publicClient = getPublicClient(anvilRpc) - const smartAccount = await signerToLightSmartAccount(publicClient, { - entryPoint, - signer: privateKeyToAccount(privateKey), - lightAccountVersion: "1.1.0" - }) + const smartAccount = privateKey + ? await privateKeyToLightSmartAccount(publicClient, { + entryPoint, + lightAccountVersion: "1.1.0", + privateKey + }) + : await signerToLightSmartAccount(publicClient, { + entryPoint, + signer: privateKeyToAccount(generatePrivateKey()), + lightAccountVersion: "1.1.0" + }) return createSmartAccountClient({ chain: foundry, @@ -239,18 +261,20 @@ export const getTrustAccountClient = async < paymasterClient, altoRpc, anvilRpc, - privateKey = generatePrivateKey() + privateKey }: AAParamType): Promise< SmartAccountClient> > => { const publicClient = getPublicClient(anvilRpc) - const smartAccount = await signerToTrustSmartAccount( - publicClient, - { - entryPoint, - signer: privateKeyToAccount(privateKey) - } - ) + const smartAccount = privateKey + ? await privateKeyToTrustSmartAccount(publicClient, { + entryPoint, + privateKey + }) + : await signerToTrustSmartAccount(publicClient, { + entryPoint, + signer: privateKeyToAccount(generatePrivateKey()) + }) // @ts-ignore return createSmartAccountClient({ @@ -267,16 +291,21 @@ export const getTrustAccountClient = async < // Only supports v0.6 for now export const getBiconomyClient = async ({ paymasterClient, - privateKey = generatePrivateKey(), + privateKey, anvilRpc, altoRpc, entryPoint = ENTRYPOINT_ADDRESS_V06 }: AAParamType) => { const publicClient = getPublicClient(anvilRpc) - const ecdsaSmartAccount = await signerToBiconomySmartAccount(publicClient, { - entryPoint, - signer: privateKeyToAccount(privateKey) - }) + const ecdsaSmartAccount = privateKey + ? await privateKeyToBiconomySmartAccount(publicClient, { + entryPoint, + privateKey + }) + : await signerToBiconomySmartAccount(publicClient, { + entryPoint, + signer: privateKeyToAccount(generatePrivateKey()) + }) // @ts-ignore return createSmartAccountClient({ @@ -295,23 +324,32 @@ export const getKernelEcdsaClient = async ({ paymasterClient, anvilRpc, altoRpc, - privateKey = generatePrivateKey() -}: AAParamType): Promise< + privateKey = generatePrivateKey(), + erc7579 +}: AAParamType & { erc7579?: boolean }): Promise< SmartAccountClient> > => { const publicClient = getPublicClient(anvilRpc) - const kernelEcdsaAccount = await signerToEcdsaKernelSmartAccount( - publicClient, - { - entryPoint, - signer: privateKeyToAccount(privateKey) - } - ) + if (erc7579 && entryPoint === ENTRYPOINT_ADDRESS_V06) { + throw new Error("ERC7579 is not supported for V06") + } + + const kernelEcdsaAccount = + erc7579 && entryPoint === ENTRYPOINT_ADDRESS_V07 + ? await signerToEcdsaKernelSmartAccount(publicClient, { + entryPoint: entryPoint as ENTRYPOINT_ADDRESS_V07_TYPE, + signer: privateKeyToAccount(privateKey), + version: "0.3.0" + }) + : await signerToEcdsaKernelSmartAccount(publicClient, { + entryPoint, + signer: privateKeyToAccount(privateKey) + }) // @ts-ignore return createSmartAccountClient({ chain: foundry, - account: kernelEcdsaAccount, + account: kernelEcdsaAccount as KernelEcdsaSmartAccount, bundlerTransport: http(altoRpc), middleware: { // @ts-ignore @@ -326,7 +364,8 @@ export const getSafeClient = async ({ paymasterClient, anvilRpc, altoRpc, - privateKey = generatePrivateKey() + privateKey, + erc7579 }: { setupTransactions?: { to: Address @@ -338,14 +377,39 @@ export const getSafeClient = async ({ entryPoint: T paymasterClient?: PimlicoPaymasterClient privateKey?: Hex + erc7579?: boolean }): Promise>> => { const publicClient = getPublicClient(anvilRpc) - const safeSmartAccount = await signerToSafeSmartAccount(publicClient, { + + const safeSmartAccount = privateKey + ? await privateKeyToSafeSmartAccount(publicClient, { + entryPoint, + privateKey, + safeVersion: "1.4.1", + saltNonce: 420n, + safe4337ModuleAddress: erc7579 + ? "0x3Fdb5BC686e861480ef99A6E3FaAe03c0b9F32e2" + : undefined, + erc7569LaunchpadAddress: erc7579 + ? "0xEBe001b3D534B9B6E2500FB78E67a1A137f561CE" + : undefined + }) + : await signerToSafeSmartAccount(publicClient, { + entryPoint, + signer: privateKeyToAccount(generatePrivateKey()), + safeVersion: "1.4.1", + saltNonce: 420n, + safe4337ModuleAddress: erc7579 + ? "0x3Fdb5BC686e861480ef99A6E3FaAe03c0b9F32e2" + : undefined, + erc7569LaunchpadAddress: erc7579 + ? "0xEBe001b3D534B9B6E2500FB78E67a1A137f561CE" + : undefined + }) + + const pimlicoBundlerClient = getPimlicoBundlerClient({ entryPoint, - signer: privateKeyToAccount(privateKey), - safeVersion: "1.4.1", - saltNonce: 420n, - setupTransactions + altoRpc }) // @ts-ignore @@ -354,6 +418,8 @@ export const getSafeClient = async ({ account: safeSmartAccount, bundlerTransport: http(altoRpc), middleware: { + gasPrice: async () => + (await pimlicoBundlerClient.getUserOperationGasPrice()).fast, // @ts-ignore sponsorUserOperation: paymasterClient?.sponsorUserOperation } @@ -436,6 +502,9 @@ export const getCoreSmartAccounts = () => [ signer: privateKeyToAccount(conf.privateKey), entryPoint: ENTRYPOINT_ADDRESS_V06 }), + getErc7579SmartAccountClient: async ( + conf: AAParamType + ) => getKernelEcdsaClient({ ...conf, erc7579: true }), supportsEntryPointV06: true, supportsEntryPointV07: true, isEip1271Compliant: true @@ -474,6 +543,116 @@ export const getCoreSmartAccounts = () => [ entryPoint: ENTRYPOINT_ADDRESS_V06, safeVersion: "1.4.1" }), + getErc7579SmartAccountClient: async ( + conf: AAParamType + ) => getSafeClient({ ...conf, erc7579: true }), + supportsEntryPointV06: true, + supportsEntryPointV07: true, + isEip1271Compliant: true + }, + + // ---------------------------- Account from private key ------------------------------------------------- + + { + name: "Trust", + getSmartAccountClient: async ( + conf: AAParamType + ) => { + if (conf.entryPoint !== ENTRYPOINT_ADDRESS_V06) { + throw new Error("Biconomy only works with V06") + } + return getTrustAccountClient({ + ...(conf as AAParamType), + privateKey: generatePrivateKey() + }) + }, + getSmartAccountSigner: async (conf: ExistingSignerParamType) => + signerToTrustSmartAccount(conf.publicClient, { + address: conf.existingAddress, // this is the field we are testing + signer: privateKeyToAccount(conf.privateKey), + entryPoint: ENTRYPOINT_ADDRESS_V06 + }), + supportsEntryPointV06: true, + supportsEntryPointV07: false, + isEip1271Compliant: true + }, + { + name: "LightAccount v1.1.0", + getSmartAccountClient: async ( + conf: AAParamType + ) => + getLightAccountClient({ + ...conf, + privateKey: generatePrivateKey() + }), + getSmartAccountSigner: async (conf: ExistingSignerParamType) => + signerToLightSmartAccount(conf.publicClient, { + address: conf.existingAddress, // this is the field we are testing + signer: privateKeyToAccount(conf.privateKey), + entryPoint: ENTRYPOINT_ADDRESS_V06, + lightAccountVersion: "1.1.0" + }), + supportsEntryPointV06: true, + supportsEntryPointV07: false, + isEip1271Compliant: true + }, + { + name: "Simple", + getSmartAccountClient: async ( + conf: AAParamType + ) => + getSimpleAccountClient({ + ...conf, + privateKey: generatePrivateKey() + }), + getSmartAccountSigner: async (conf: ExistingSignerParamType) => + signerToSimpleSmartAccount(conf.publicClient, { + address: conf.existingAddress, // this is the field we are testing + signer: privateKeyToAccount(conf.privateKey), + entryPoint: ENTRYPOINT_ADDRESS_V06 + }), + supportsEntryPointV06: true, + supportsEntryPointV07: true, + isEip1271Compliant: false + }, + { + name: "Biconomy", + getSmartAccountClient: async ( + conf: AAParamType + ) => { + if (conf.entryPoint !== ENTRYPOINT_ADDRESS_V06) { + throw new Error("Biconomy only works with V06") + } + return getBiconomyClient({ + ...(conf as AAParamType), + privateKey: generatePrivateKey() + }) + }, + getSmartAccountSigner: async (conf: ExistingSignerParamType) => + signerToBiconomySmartAccount(conf.publicClient, { + address: conf.existingAddress, // this is the field we are testing + signer: privateKeyToAccount(conf.privateKey), + entryPoint: ENTRYPOINT_ADDRESS_V06 + }), + supportsEntryPointV06: true, + supportsEntryPointV07: false, + isEip1271Compliant: true + }, + { + name: "Safe", + getSmartAccountClient: async ( + conf: AAParamType + ) => getSafeClient({ ...conf, privateKey: generatePrivateKey() }), + getSmartAccountSigner: async (conf: ExistingSignerParamType) => + signerToSafeSmartAccount(conf.publicClient, { + address: conf.existingAddress, // this is the field we are testing + signer: privateKeyToAccount(conf.privateKey), + entryPoint: ENTRYPOINT_ADDRESS_V06, + safeVersion: "1.4.1" + }), + getErc7579SmartAccountClient: async ( + conf: AAParamType + ) => getSafeClient({ ...conf, erc7579: true }), supportsEntryPointV06: true, supportsEntryPointV07: true, isEip1271Compliant: true diff --git a/packages/permissionless/accounts/biconomy/privateKeyToBiconomySmartAccount.ts b/packages/permissionless/accounts/biconomy/privateKeyToBiconomySmartAccount.ts index 3cdd2e0e..82c1160f 100644 --- a/packages/permissionless/accounts/biconomy/privateKeyToBiconomySmartAccount.ts +++ b/packages/permissionless/accounts/biconomy/privateKeyToBiconomySmartAccount.ts @@ -1,4 +1,11 @@ -import type { Chain, Client, Hex, Transport } from "viem" +import type { + Chain, + Client, + Hex, + PublicActions, + PublicRpcSchema, + Transport +} from "viem" import { privateKeyToAccount } from "viem/accounts" import type { ENTRYPOINT_ADDRESS_V06_TYPE, Prettify } from "../../types" import { @@ -25,7 +32,13 @@ export async function privateKeyToBiconomySmartAccount< TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { privateKey, ...rest diff --git a/packages/permissionless/accounts/biconomy/signerToBiconomySmartAccount.ts b/packages/permissionless/accounts/biconomy/signerToBiconomySmartAccount.ts index 14860e35..6866ec36 100644 --- a/packages/permissionless/accounts/biconomy/signerToBiconomySmartAccount.ts +++ b/packages/permissionless/accounts/biconomy/signerToBiconomySmartAccount.ts @@ -1,4 +1,4 @@ -import type { TypedData } from "viem" +import type { PublicActions, PublicRpcSchema, TypedData } from "viem" import { type Address, type Chain, @@ -187,6 +187,7 @@ export type SignerToBiconomySmartAccountParameters< TSource extends string = string, TAddress extends Address = Address > = Prettify<{ + nonceKey?: bigint signer: SmartAccountSigner entryPoint: entryPoint address?: Address @@ -214,7 +215,13 @@ export async function signerToBiconomySmartAccount< TSource extends string = string, TAddress extends Address = Address >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { signer, address, @@ -223,7 +230,8 @@ export async function signerToBiconomySmartAccount< factoryAddress = BICONOMY_ADDRESSES.FACTORY_ADDRESS, accountLogicAddress = BICONOMY_ADDRESSES.ACCOUNT_V2_0_LOGIC, fallbackHandlerAddress = BICONOMY_ADDRESSES.DEFAULT_FALLBACK_HANDLER_ADDRESS, - ecdsaModuleAddress = BICONOMY_ADDRESSES.ECDSA_OWNERSHIP_REGISTRY_MODULE + ecdsaModuleAddress = BICONOMY_ADDRESSES.ECDSA_OWNERSHIP_REGISTRY_MODULE, + nonceKey }: SignerToBiconomySmartAccountParameters ): Promise> { const entryPointVersion = getEntryPointVersion(entryPointAddress) @@ -328,10 +336,11 @@ export async function signerToBiconomySmartAccount< source: "biconomySmartAccount", // Get the nonce of the smart account - async getNonce() { + async getNonce(key?: bigint) { return getAccountNonce(client, { sender: accountAddress, - entryPoint: entryPointAddress + entryPoint: entryPointAddress, + key: key ?? nonceKey }) }, diff --git a/packages/permissionless/accounts/kernel/signerToEcdsaKernelSmartAccount.ts b/packages/permissionless/accounts/kernel/signerToEcdsaKernelSmartAccount.ts index 4d0795e5..1b4e3955 100644 --- a/packages/permissionless/accounts/kernel/signerToEcdsaKernelSmartAccount.ts +++ b/packages/permissionless/accounts/kernel/signerToEcdsaKernelSmartAccount.ts @@ -1,4 +1,4 @@ -import type { TypedData } from "viem" +import type { PublicActions, PublicRpcSchema, TypedData } from "viem" import { type Address, type Chain, @@ -45,6 +45,7 @@ import { } from "./constants" import { encodeCallData } from "./utils/encodeCallData" import { getNonceKeyWithEncoding } from "./utils/getNonceKey" +import { isKernelV2 } from "./utils/isKernelV2" import { signMessage } from "./utils/signMessage" import { signTypedData } from "./utils/signTypedData" @@ -89,29 +90,53 @@ const createAccountAbi = [ } ] as const -export type KernelVersion = "0.2.2" | "0.3.0-beta" +export type KernelVersion = + entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE + ? "0.2.1" | "0.2.2" | "0.2.3" | "0.2.4" + : "0.3.0" | "0.3.1" /** * Default addresses map for different kernel smart account versions */ export const KERNEL_VERSION_TO_ADDRESSES_MAP: { - [key in KernelVersion]: { + [key in KernelVersion]: { ECDSA_VALIDATOR: Address ACCOUNT_LOGIC: Address FACTORY_ADDRESS: Address META_FACTORY_ADDRESS?: Address } } = { + "0.2.1": { + ECDSA_VALIDATOR: "0xd9AB5096a832b9ce79914329DAEE236f8Eea0390", + ACCOUNT_LOGIC: "0xf048AD83CB2dfd6037A43902a2A5Be04e53cd2Eb", + FACTORY_ADDRESS: "0x5de4839a76cf55d0c90e2061ef4386d962E15ae3" + }, "0.2.2": { ECDSA_VALIDATOR: "0xd9AB5096a832b9ce79914329DAEE236f8Eea0390", ACCOUNT_LOGIC: "0x0DA6a956B9488eD4dd761E59f52FDc6c8068E6B5", FACTORY_ADDRESS: "0x5de4839a76cf55d0c90e2061ef4386d962E15ae3" }, - "0.3.0-beta": { + "0.2.3": { + ECDSA_VALIDATOR: "0xd9AB5096a832b9ce79914329DAEE236f8Eea0390", + ACCOUNT_LOGIC: "0xD3F582F6B4814E989Ee8E96bc3175320B5A540ab", + FACTORY_ADDRESS: "0x5de4839a76cf55d0c90e2061ef4386d962E15ae3" + }, + "0.2.4": { + ECDSA_VALIDATOR: "0xd9AB5096a832b9ce79914329DAEE236f8Eea0390", + ACCOUNT_LOGIC: "0xd3082872F8B06073A021b4602e022d5A070d7cfC", + FACTORY_ADDRESS: "0x5de4839a76cf55d0c90e2061ef4386d962E15ae3" + }, + "0.3.0": { ECDSA_VALIDATOR: "0x8104e3Ad430EA6d354d013A6789fDFc71E671c43", ACCOUNT_LOGIC: "0x94F097E1ebEB4ecA3AAE54cabb08905B239A7D27", FACTORY_ADDRESS: "0x6723b44Abeec4E71eBE3232BD5B455805baDD22f", META_FACTORY_ADDRESS: "0xd703aaE79538628d27099B8c4f621bE4CCd142d5" + }, + "0.3.1": { + ECDSA_VALIDATOR: "0x845ADb2C711129d4f3966735eD98a9F09fC4cE57", + ACCOUNT_LOGIC: "0xBAC849bB641841b44E965fB01A4Bf5F074f84b4D", + FACTORY_ADDRESS: "0xaac5D4240AF87249B3f71BC8E4A2cae074A3E419", + META_FACTORY_ADDRESS: "0xd703aaE79538628d27099B8c4f621bE4CCd142d5" } } @@ -119,8 +144,16 @@ export const KERNEL_VERSION_TO_ADDRESSES_MAP: { * Get supported Kernel Smart Account version based on entryPoint * @param entryPoint */ -const getKernelVersion = (entryPoint: EntryPoint): KernelVersion => { - return entryPoint === ENTRYPOINT_ADDRESS_V06 ? "0.2.2" : "0.3.0-beta" +const getDefaultKernelVersion = ( + entryPoint: TEntryPoint, + version?: KernelVersion +): KernelVersion => { + if (version) { + return version + } + return ( + entryPoint === ENTRYPOINT_ADDRESS_V06 ? "0.2.2" : "0.3.0" + ) as KernelVersion } type KERNEL_ADDRESSES = { @@ -138,16 +171,15 @@ type KERNEL_ADDRESSES = { * @param factoryAddress * @param metaFactoryAddress */ -const getDefaultAddresses = ( - entryPointAddress: entryPoint, - { - ecdsaValidatorAddress: _ecdsaValidatorAddress, - accountLogicAddress: _accountLogicAddress, - factoryAddress: _factoryAddress, - metaFactoryAddress: _metaFactoryAddress - }: Partial -): KERNEL_ADDRESSES => { - const kernelVersion = getKernelVersion(entryPointAddress) +const getDefaultAddresses = ({ + ecdsaValidatorAddress: _ecdsaValidatorAddress, + accountLogicAddress: _accountLogicAddress, + factoryAddress: _factoryAddress, + metaFactoryAddress: _metaFactoryAddress, + kernelVersion +}: Partial & { + kernelVersion: KernelVersion +}): KERNEL_ADDRESSES => { const addresses = KERNEL_VERSION_TO_ADDRESSES_MAP[kernelVersion] const ecdsaValidatorAddress = _ecdsaValidatorAddress ?? addresses.ECDSA_VALIDATOR @@ -351,6 +383,7 @@ export type SignerToEcdsaKernelSmartAccountParameters< TAddress extends Address = Address > = Prettify<{ signer: SmartAccountSigner + version?: KernelVersion entryPoint: entryPoint address?: Address index?: bigint @@ -359,6 +392,7 @@ export type SignerToEcdsaKernelSmartAccountParameters< accountLogicAddress?: Address ecdsaValidatorAddress?: Address deployedAccountAddress?: Address + nonceKey?: bigint }> /** * Build a kernel smart account from a private key, that use the ECDSA signer behind the scene @@ -378,32 +412,41 @@ export async function signerToEcdsaKernelSmartAccount< TSource extends string = string, TAddress extends Address = Address >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { signer, address, + version, entryPoint: entryPointAddress, index = BigInt(0), factoryAddress: _factoryAddress, metaFactoryAddress: _metaFactoryAddress, accountLogicAddress: _accountLogicAddress, ecdsaValidatorAddress: _ecdsaValidatorAddress, - deployedAccountAddress + deployedAccountAddress, + nonceKey }: SignerToEcdsaKernelSmartAccountParameters ): Promise> { const entryPointVersion = getEntryPointVersion(entryPointAddress) - const kernelVersion = getKernelVersion(entryPointAddress) + const kernelVersion = getDefaultKernelVersion(entryPointAddress, version) const { accountLogicAddress, ecdsaValidatorAddress, factoryAddress, metaFactoryAddress - } = getDefaultAddresses(entryPointAddress, { + } = getDefaultAddresses({ ecdsaValidatorAddress: _ecdsaValidatorAddress, accountLogicAddress: _accountLogicAddress, factoryAddress: _factoryAddress, - metaFactoryAddress: _metaFactoryAddress + metaFactoryAddress: _metaFactoryAddress, + kernelVersion }) // Get the private key related account @@ -461,7 +504,7 @@ export async function signerToEcdsaKernelSmartAccount< chainId }) - if (kernelVersion === "0.2.2") { + if (isKernelV2(kernelVersion)) { return signature } @@ -492,7 +535,7 @@ export async function signerToEcdsaKernelSmartAccount< chainId }) - if (kernelVersion === "0.2.2") { + if (isKernelV2(kernelVersion)) { return signature } @@ -507,17 +550,19 @@ export async function signerToEcdsaKernelSmartAccount< source: "kernelEcdsaSmartAccount", // Get the nonce of the smart account - async getNonce() { - const key = getNonceKeyWithEncoding( - kernelVersion, - ecdsaValidatorAddress - // @dev specify the custom nonceKey here when integrating the said feature - /*, nonceKey */ - ) + async getNonce(key?: bigint) { return getAccountNonce(client, { sender: accountAddress, entryPoint: entryPointAddress, - key + key: + key ?? + nonceKey ?? + getNonceKeyWithEncoding( + kernelVersion, + ecdsaValidatorAddress + // @dev specify the custom nonceKey here when integrating the said feature + /*, nonceKey */ + ) }) }, @@ -536,7 +581,7 @@ export async function signerToEcdsaKernelSmartAccount< message: { raw: hash } }) // Always use the sudo mode, since we will use external paymaster - if (kernelVersion === "0.2.2") { + if (isKernelV2(kernelVersion)) { return concatHex(["0x00000000", signature]) } return signature @@ -600,7 +645,7 @@ export async function signerToEcdsaKernelSmartAccount< // Get simple dummy signature async getDummySignature(_userOperation) { - if (kernelVersion === "0.2.2") { + if (isKernelV2(kernelVersion)) { return concatHex([ROOT_MODE_KERNEL_V2, DUMMY_ECDSA_SIGNATURE]) } return DUMMY_ECDSA_SIGNATURE diff --git a/packages/permissionless/accounts/kernel/utils/encodeCallData.ts b/packages/permissionless/accounts/kernel/utils/encodeCallData.ts index 4e573e2a..deac9b3b 100644 --- a/packages/permissionless/accounts/kernel/utils/encodeCallData.ts +++ b/packages/permissionless/accounts/kernel/utils/encodeCallData.ts @@ -6,11 +6,13 @@ import { encodeFunctionData, toHex } from "viem" +import type { EntryPoint } from "../../../types" import { KernelExecuteAbi } from "../abi/KernelAccountAbi" import { KernelV3ExecuteAbi } from "../abi/KernelV3AccountAbi" import { CALL_TYPE, EXEC_TYPE } from "../constants" import type { KernelVersion } from "../signerToEcdsaKernelSmartAccount" import { getExecMode } from "./getExecMode" +import { isKernelV2 } from "./isKernelV2" export const encodeCallData = ( _tx: @@ -24,9 +26,9 @@ export const encodeCallData = ( value: bigint data: Hex }[], - accountVersion: KernelVersion + accountVersion: KernelVersion ) => { - if (accountVersion === "0.2.2") { + if (isKernelV2(accountVersion)) { if (Array.isArray(_tx)) { // Encode a batched call return encodeFunctionData({ diff --git a/packages/permissionless/accounts/kernel/utils/getNonceKey.ts b/packages/permissionless/accounts/kernel/utils/getNonceKey.ts index b8dfbc99..92702549 100644 --- a/packages/permissionless/accounts/kernel/utils/getNonceKey.ts +++ b/packages/permissionless/accounts/kernel/utils/getNonceKey.ts @@ -1,13 +1,15 @@ import { type Address, concatHex, maxUint16, pad, toHex } from "viem" +import type { EntryPoint } from "../../../types" import { VALIDATOR_MODE, VALIDATOR_TYPE } from "../constants" import type { KernelVersion } from "../signerToEcdsaKernelSmartAccount" +import { isKernelV2 } from "./isKernelV2" export const getNonceKeyWithEncoding = ( - accountVerion: KernelVersion, + accountVerion: KernelVersion, validatorAddress: Address, nonceKey = 0n ) => { - if (accountVerion === "0.2.2") { + if (isKernelV2(accountVerion)) { return nonceKey } diff --git a/packages/permissionless/accounts/kernel/utils/isKernelV2.ts b/packages/permissionless/accounts/kernel/utils/isKernelV2.ts new file mode 100644 index 00000000..68476b63 --- /dev/null +++ b/packages/permissionless/accounts/kernel/utils/isKernelV2.ts @@ -0,0 +1,7 @@ +import type { EntryPoint } from "../../../types" +import type { KernelVersion } from "../signerToEcdsaKernelSmartAccount" + +export const isKernelV2 = (version: KernelVersion): boolean => { + const regex = /0\.2\.\d+/ + return regex.test(version) +} diff --git a/packages/permissionless/accounts/kernel/utils/signMessage.ts b/packages/permissionless/accounts/kernel/utils/signMessage.ts index 27821ba1..98860ff5 100644 --- a/packages/permissionless/accounts/kernel/utils/signMessage.ts +++ b/packages/permissionless/accounts/kernel/utils/signMessage.ts @@ -10,6 +10,7 @@ import { publicActions } from "viem" import { signMessage as _signMessage } from "viem/actions" +import { isKernelV2 } from "./isKernelV2" import { type WrapMessageHashParams, wrapMessageHash } from "./wrapMessageHash" export async function signMessage< @@ -24,7 +25,7 @@ export async function signMessage< accountVersion }: SignMessageParameters & WrapMessageHashParams ): Promise { - if (accountVersion === "0.2.2") { + if (isKernelV2(accountVersion)) { return _signMessage(client, { account: account_ as LocalAccount, message diff --git a/packages/permissionless/accounts/kernel/utils/signTypedData.ts b/packages/permissionless/accounts/kernel/utils/signTypedData.ts index a75f1cc9..901bc204 100644 --- a/packages/permissionless/accounts/kernel/utils/signTypedData.ts +++ b/packages/permissionless/accounts/kernel/utils/signTypedData.ts @@ -17,6 +17,7 @@ import { signMessage as _signMessage, signTypedData as _signTypedData } from "viem/actions" +import { isKernelV2 } from "./isKernelV2" import { type WrapMessageHashParams, wrapMessageHash } from "./wrapMessageHash" export async function signTypedData< @@ -35,7 +36,7 @@ export async function signTypedData< accountVersion, ...typedData } = parameters as unknown as SignTypedDataParameters & WrapMessageHashParams - if (accountVersion === "0.2.2") { + if (isKernelV2(accountVersion)) { return _signTypedData(client, { account: account_, ...typedData }) } const { message, primaryType, types: _types, domain } = typedData diff --git a/packages/permissionless/accounts/kernel/utils/wrapMessageHash.ts b/packages/permissionless/accounts/kernel/utils/wrapMessageHash.ts index 2d7352f3..47b5ff20 100644 --- a/packages/permissionless/accounts/kernel/utils/wrapMessageHash.ts +++ b/packages/permissionless/accounts/kernel/utils/wrapMessageHash.ts @@ -6,9 +6,11 @@ import { stringToHex } from "viem" import { type Address, domainSeparator } from "viem" +import type { EntryPoint } from "../../../types" +import type { KernelVersion } from "../signerToEcdsaKernelSmartAccount" export type WrapMessageHashParams = { - accountVersion: string + accountVersion: KernelVersion accountAddress: Address chainId?: number } diff --git a/packages/permissionless/accounts/light/privateKeyToLightSmartAccount.ts b/packages/permissionless/accounts/light/privateKeyToLightSmartAccount.ts index e4400743..bd2ab349 100644 --- a/packages/permissionless/accounts/light/privateKeyToLightSmartAccount.ts +++ b/packages/permissionless/accounts/light/privateKeyToLightSmartAccount.ts @@ -1,6 +1,14 @@ -import type { Chain, Client, Hex, Transport } from "viem" +import type { + Chain, + Client, + Hex, + PublicActions, + PublicRpcSchema, + Transport +} from "viem" import { privateKeyToAccount } from "viem/accounts" -import type { ENTRYPOINT_ADDRESS_V06_TYPE, Prettify } from "../../types" +import type { Prettify } from "../../types" +import type { EntryPoint } from "../../types" import { type LightSmartAccount, type SignerToLightSmartAccountParameters, @@ -8,7 +16,7 @@ import { } from "./signerToLightSmartAccount" export type PrivateKeyToLightSmartAccountParameters< - entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE + entryPoint extends EntryPoint > = Prettify< { privateKey: Hex @@ -21,11 +29,17 @@ export type PrivateKeyToLightSmartAccountParameters< * @returns A Private Key Light Account. */ export async function privateKeyToLightSmartAccount< - entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE, + entryPoint extends EntryPoint, TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { privateKey, ...rest }: PrivateKeyToLightSmartAccountParameters ): Promise> { const privateKeyAccount = privateKeyToAccount(privateKey) diff --git a/packages/permissionless/accounts/light/signerToLightSmartAccount.ts b/packages/permissionless/accounts/light/signerToLightSmartAccount.ts index 67e3d058..b73b770b 100644 --- a/packages/permissionless/accounts/light/signerToLightSmartAccount.ts +++ b/packages/permissionless/accounts/light/signerToLightSmartAccount.ts @@ -4,6 +4,8 @@ import { type Client, type Hex, type LocalAccount, + type PublicActions, + type PublicRpcSchema, type Transport, type TypedData, type TypedDataDefinition, @@ -124,6 +126,7 @@ export type SignerToLightSmartAccountParameters< factoryAddress?: Address index?: bigint address?: Address + nonceKey?: bigint }> async function signWith1271WrapperV1< @@ -191,14 +194,21 @@ export async function signerToLightSmartAccount< TSource extends string = string, TAddress extends Address = Address >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { signer, address, lightAccountVersion, entryPoint: entryPointAddress, index = BigInt(0), - factoryAddress: _factoryAddress + factoryAddress: _factoryAddress, + nonceKey }: SignerToLightSmartAccountParameters ): Promise> { const viemSigner: LocalAccount = { @@ -267,10 +277,11 @@ export async function signerToLightSmartAccount< publicKey: accountAddress, entryPoint: entryPointAddress, source: "LightSmartAccount", - async getNonce() { + async getNonce(key?: bigint) { return getAccountNonce(client, { sender: accountAddress, - entryPoint: entryPointAddress + entryPoint: entryPointAddress, + key: key ?? nonceKey }) }, async signUserOperation(userOperation) { diff --git a/packages/permissionless/accounts/safe/privateKeyToSafeSmartAccount.ts b/packages/permissionless/accounts/safe/privateKeyToSafeSmartAccount.ts index a482cb97..80eeecb8 100644 --- a/packages/permissionless/accounts/safe/privateKeyToSafeSmartAccount.ts +++ b/packages/permissionless/accounts/safe/privateKeyToSafeSmartAccount.ts @@ -1,6 +1,13 @@ -import type { Chain, Client, Hex, Transport } from "viem" +import type { + Chain, + Client, + Hex, + PublicActions, + PublicRpcSchema, + Transport +} from "viem" import { privateKeyToAccount } from "viem/accounts" -import type { ENTRYPOINT_ADDRESS_V06_TYPE, Prettify } from "../../types" +import type { EntryPoint, Prettify } from "../../types" import { type SafeSmartAccount, type SignerToSafeSmartAccountParameters, @@ -8,7 +15,7 @@ import { } from "./signerToSafeSmartAccount" export type PrivateKeyToSafeSmartAccountParameters< - entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE + entryPoint extends EntryPoint > = Prettify< { privateKey: Hex @@ -21,11 +28,17 @@ export type PrivateKeyToSafeSmartAccountParameters< * @returns A Private Key Simple Account. */ export async function privateKeyToSafeSmartAccount< - entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE, + entryPoint extends EntryPoint, TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { privateKey, ...rest }: PrivateKeyToSafeSmartAccountParameters ): Promise> { const privateKeyAccount = privateKeyToAccount(privateKey) diff --git a/packages/permissionless/accounts/safe/signerToSafeSmartAccount.ts b/packages/permissionless/accounts/safe/signerToSafeSmartAccount.ts index fd3e539a..cc252556 100644 --- a/packages/permissionless/accounts/safe/signerToSafeSmartAccount.ts +++ b/packages/permissionless/accounts/safe/signerToSafeSmartAccount.ts @@ -4,12 +4,15 @@ import { type Client, type Hex, type LocalAccount, + type PublicActions, + type PublicRpcSchema, type SignableMessage, type Transport, type TypedData, type TypedDataDefinition, concat, concatHex, + encodeAbiParameters, encodeFunctionData, encodePacked, getContractAddress, @@ -29,12 +32,9 @@ import { signTypedData } from "viem/actions" import { getAccountNonce } from "../../actions/public/getAccountNonce" -import type { - EntryPointVersion, - GetEntryPointVersion, - Prettify -} from "../../types" +import type { EntryPointVersion, GetEntryPointVersion } from "../../types" import type { EntryPoint, UserOperation } from "../../types" +import { encode7579CallData } from "../../utils/encode7579CallData" import { getEntryPointVersion, isUserOperationVersion06, @@ -50,6 +50,341 @@ import { export type SafeVersion = "1.4.1" +const multiSendAbi = [ + { + inputs: [ + { + internalType: "bytes", + name: "transactions", + type: "bytes" + } + ], + name: "multiSend", + outputs: [], + stateMutability: "payable", + type: "function" + } +] as const + +const initSafe7579Abi = [ + { + type: "function", + name: "initSafe7579", + inputs: [ + { + name: "safe7579", + type: "address", + internalType: "address" + }, + { + name: "executors", + type: "tuple[]", + internalType: "struct ModuleInit[]", + components: [ + { + name: "module", + type: "address", + internalType: "address" + }, + { + name: "initData", + type: "bytes", + internalType: "bytes" + } + ] + }, + { + name: "fallbacks", + type: "tuple[]", + internalType: "struct ModuleInit[]", + components: [ + { + name: "module", + type: "address", + internalType: "address" + }, + { + name: "initData", + type: "bytes", + internalType: "bytes" + } + ] + }, + { + name: "hooks", + type: "tuple[]", + internalType: "struct ModuleInit[]", + components: [ + { + name: "module", + type: "address", + internalType: "address" + }, + { + name: "initData", + type: "bytes", + internalType: "bytes" + } + ] + }, + { + name: "attesters", + type: "address[]", + internalType: "address[]" + }, + { + name: "threshold", + type: "uint8", + internalType: "uint8" + } + ], + outputs: [], + stateMutability: "nonpayable" + } +] as const + +const preValidationSetupAbi = [ + { + type: "function", + name: "preValidationSetup", + inputs: [ + { + name: "initHash", + type: "bytes32", + internalType: "bytes32" + }, + { + name: "to", + type: "address", + internalType: "address" + }, + { + name: "preInit", + type: "bytes", + internalType: "bytes" + } + ], + outputs: [], + stateMutability: "nonpayable" + } +] as const + +const enableModulesAbi = [ + { + inputs: [ + { + internalType: "address[]", + name: "modules", + type: "address[]" + } + ], + name: "enableModules", + outputs: [], + stateMutability: "nonpayable", + type: "function" + } +] as const + +const setupAbi = [ + { + inputs: [ + { + internalType: "address[]", + name: "_owners", + type: "address[]" + }, + { + internalType: "uint256", + name: "_threshold", + type: "uint256" + }, + { + internalType: "address", + name: "to", + type: "address" + }, + { + internalType: "bytes", + name: "data", + type: "bytes" + }, + { + internalType: "address", + name: "fallbackHandler", + type: "address" + }, + { + internalType: "address", + name: "paymentToken", + type: "address" + }, + { + internalType: "uint256", + name: "payment", + type: "uint256" + }, + { + internalType: "address payable", + name: "paymentReceiver", + type: "address" + } + ], + name: "setup", + outputs: [], + stateMutability: "nonpayable", + type: "function" + } +] as const + +const createProxyWithNonceAbi = [ + { + inputs: [ + { + internalType: "address", + name: "_singleton", + type: "address" + }, + { + internalType: "bytes", + name: "initializer", + type: "bytes" + }, + { + internalType: "uint256", + name: "saltNonce", + type: "uint256" + } + ], + name: "createProxyWithNonce", + outputs: [ + { + internalType: "contract SafeProxy", + name: "proxy", + type: "address" + } + ], + stateMutability: "nonpayable", + type: "function" + } +] as const + +const proxyCreationCodeAbi = [ + { + inputs: [], + name: "proxyCreationCode", + outputs: [ + { + internalType: "bytes", + name: "", + type: "bytes" + } + ], + stateMutability: "pure", + type: "function" + } +] as const + +const setupSafeAbi = [ + { + type: "function", + name: "setupSafe", + inputs: [ + { + name: "initData", + type: "tuple", + internalType: "struct Safe7579Launchpad.InitData", + components: [ + { + name: "singleton", + type: "address", + internalType: "address" + }, + { + name: "owners", + type: "address[]", + internalType: "address[]" + }, + { + name: "threshold", + type: "uint256", + internalType: "uint256" + }, + { + name: "setupTo", + type: "address", + internalType: "address" + }, + { + name: "setupData", + type: "bytes", + internalType: "bytes" + }, + { + name: "safe7579", + type: "address", + internalType: "contract ISafe7579" + }, + { + name: "validators", + type: "tuple[]", + internalType: "struct ModuleInit[]", + components: [ + { + name: "module", + type: "address", + internalType: "address" + }, + { + name: "initData", + type: "bytes", + internalType: "bytes" + } + ] + }, + { + name: "callData", + type: "bytes", + internalType: "bytes" + } + ] + } + ], + outputs: [], + stateMutability: "nonpayable" + } +] as const + +const executeUserOpWithErrorStringAbi = [ + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address" + }, + { + internalType: "uint256", + name: "value", + type: "uint256" + }, + { + internalType: "bytes", + name: "data", + type: "bytes" + }, + { + internalType: "uint8", + name: "operation", + type: "uint8" + } + ], + name: "executeUserOpWithErrorString", + outputs: [], + stateMutability: "nonpayable", + type: "function" + } +] as const + const EIP712_SAFE_OPERATION_TYPE_V06 = { SafeOp: [ { type: "address", name: "safe" }, @@ -201,21 +536,7 @@ const encodeMultiSend = ( .join("")}` return encodeFunctionData({ - abi: [ - { - inputs: [ - { - internalType: "bytes", - name: "transactions", - type: "bytes" - } - ], - name: "multiSend", - outputs: [], - stateMutability: "payable", - type: "function" - } - ], + abi: multiSendAbi, functionName: "multiSend", args: [data] }) @@ -227,104 +548,206 @@ export type SafeSmartAccount< chain extends Chain | undefined = Chain | undefined > = SmartAccount +const get7579LaunchPadInitData = ({ + safe4337ModuleAddress, + safeSingletonAddress, + erc7569LaunchpadAddress, + owner, + validators, + executors, + fallbacks, + hooks, + attesters, + attestersThreshold +}: { + safe4337ModuleAddress: Address + safeSingletonAddress: Address + erc7569LaunchpadAddress: Address + owner: Address + executors: { + address: Address + context: Address + }[] + validators: { address: Address; context: Address }[] + fallbacks: { address: Address; context: Address }[] + hooks: { address: Address; context: Address }[] + attesters: Address[] + attestersThreshold: number +}) => { + const initData = { + singleton: safeSingletonAddress, + owners: [owner], + threshold: BigInt(1), + setupTo: erc7569LaunchpadAddress, + setupData: encodeFunctionData({ + abi: initSafe7579Abi, + functionName: "initSafe7579", + args: [ + safe4337ModuleAddress, // SAFE_7579_ADDRESS, + executors.map((executor) => ({ + module: executor.address, + initData: executor.context + })), + fallbacks.map((fallback) => ({ + module: fallback.address, + initData: fallback.context + })), + hooks.map((hook) => ({ + module: hook.address, + initData: hook.context + })), + attesters, + attestersThreshold + ] + }), + safe7579: safe4337ModuleAddress, + validators: validators + } + + return initData +} + const getInitializerCode = async ({ owner, safeModuleSetupAddress, safe4337ModuleAddress, multiSendAddress, + safeSingletonAddress, + erc7569LaunchpadAddress, setupTransactions = [], - safeModules = [] + safeModules = [], + validators = [], + executors = [], + fallbacks = [], + hooks = [], + attesters = [], + attestersThreshold = 0 }: { owner: Address + safeSingletonAddress: Address safeModuleSetupAddress: Address safe4337ModuleAddress: Address multiSendAddress: Address + erc7569LaunchpadAddress?: Address setupTransactions?: { to: Address data: Address value: bigint }[] safeModules?: Address[] + validators?: { address: Address; context: Address }[] + executors?: { + address: Address + context: Address + }[] + fallbacks?: { address: Address; context: Address }[] + hooks?: { address: Address; context: Address }[] + attesters?: Address[] + attestersThreshold?: number }) => { - const multiSendCallData = encodeMultiSend([ - { - to: safeModuleSetupAddress, - data: encodeFunctionData({ - abi: [ - { - inputs: [ - { - internalType: "address[]", - name: "modules", - type: "address[]" - } - ], - name: "enableModules", - outputs: [], - stateMutability: "nonpayable", - type: "function" - } - ], - functionName: "enableModules", - args: [[safe4337ModuleAddress, ...safeModules]] - }), - value: BigInt(0), - operation: 1 - }, - ...setupTransactions.map((tx) => ({ ...tx, operation: 0 as 0 | 1 })) - ]) + if (erc7569LaunchpadAddress) { + const initData = get7579LaunchPadInitData({ + safe4337ModuleAddress, + safeSingletonAddress, + erc7569LaunchpadAddress, + owner, + validators, + executors, + fallbacks, + hooks, + attesters, + attestersThreshold + }) - return encodeFunctionData({ - abi: [ - { - inputs: [ + const initHash = keccak256( + encodeAbiParameters( + [ + { + internalType: "address", + name: "singleton", + type: "address" + }, { internalType: "address[]", - name: "_owners", + name: "owners", type: "address[]" }, { internalType: "uint256", - name: "_threshold", + name: "threshold", type: "uint256" }, { internalType: "address", - name: "to", + name: "setupTo", type: "address" }, { internalType: "bytes", - name: "data", + name: "setupData", type: "bytes" }, { - internalType: "address", - name: "fallbackHandler", + internalType: "contract ISafe7579", + name: "safe7579", type: "address" }, { - internalType: "address", - name: "paymentToken", - type: "address" - }, - { - internalType: "uint256", - name: "payment", - type: "uint256" - }, - { - internalType: "address payable", - name: "paymentReceiver", - type: "address" + internalType: "struct ModuleInit[]", + name: "validators", + type: "tuple[]", + components: [ + { + internalType: "address", + name: "module", + type: "address" + }, + { + internalType: "bytes", + name: "initData", + type: "bytes" + } + ] } ], - name: "setup", - outputs: [], - stateMutability: "nonpayable", - type: "function" - } - ], + [ + initData.singleton, + initData.owners, + initData.threshold, + initData.setupTo, + initData.setupData, + initData.safe7579, + initData.validators.map((validator) => ({ + module: validator.address, + initData: validator.context + })) + ] + ) + ) + + return encodeFunctionData({ + abi: preValidationSetupAbi, + functionName: "preValidationSetup", + args: [initHash, zeroAddress, "0x"] + }) + } + + const multiSendCallData = encodeMultiSend([ + { + to: safeModuleSetupAddress, + data: encodeFunctionData({ + abi: enableModulesAbi, + functionName: "enableModules", + args: [[safe4337ModuleAddress, ...safeModules]] + }), + value: BigInt(0), + operation: 1 + }, + ...setupTransactions.map((tx) => ({ ...tx, operation: 0 as 0 | 1 })) + ]) + + return encodeFunctionData({ + abi: setupAbi, functionName: "setup", args: [ [owner], @@ -370,16 +793,24 @@ const getAccountInitCode = async ({ safeModuleSetupAddress, safe4337ModuleAddress, safeSingletonAddress, + erc7569LaunchpadAddress, multiSendAddress, saltNonce = BigInt(0), setupTransactions = [], - safeModules = [] + safeModules = [], + validators = [], + executors = [], + fallbacks = [], + hooks = [], + attesters = [], + attestersThreshold = 0 }: { owner: Address safeModuleSetupAddress: Address safe4337ModuleAddress: Address safeSingletonAddress: Address multiSendAddress: Address + erc7569LaunchpadAddress?: Address saltNonce?: bigint setupTransactions?: { to: Address @@ -387,51 +818,45 @@ const getAccountInitCode = async ({ value: bigint }[] safeModules?: Address[] + validators?: { address: Address; context: Address }[] + executors?: { + address: Address + context: Address + }[] + fallbacks?: { address: Address; context: Address }[] + hooks?: { address: Address; context: Address }[] + attesters?: Address[] + attestersThreshold?: number }): Promise => { - if (!owner) throw new Error("Owner account not found") + if (!owner) { + throw new Error("Owner account not found") + } + const initializer = await getInitializerCode({ owner, safeModuleSetupAddress, safe4337ModuleAddress, multiSendAddress, setupTransactions, - safeModules + safeSingletonAddress, + safeModules, + erc7569LaunchpadAddress, + validators, + executors, + fallbacks, + hooks, + attesters, + attestersThreshold }) const initCodeCallData = encodeFunctionData({ - abi: [ - { - inputs: [ - { - internalType: "address", - name: "_singleton", - type: "address" - }, - { - internalType: "bytes", - name: "initializer", - type: "bytes" - }, - { - internalType: "uint256", - name: "saltNonce", - type: "uint256" - } - ], - name: "createProxyWithNonce", - outputs: [ - { - internalType: "contract SafeProxy", - name: "proxy", - type: "address" - } - ], - stateMutability: "nonpayable", - type: "function" - } - ], + abi: createProxyWithNonceAbi, functionName: "createProxyWithNonce", - args: [safeSingletonAddress, initializer, saltNonce] + args: [ + erc7569LaunchpadAddress ?? safeSingletonAddress, + initializer, + saltNonce + ] }) return initCodeCallData @@ -448,9 +873,16 @@ const getAccountAddress = async < safeProxyFactoryAddress, safeSingletonAddress, multiSendAddress, + erc7569LaunchpadAddress, setupTransactions = [], safeModules = [], - saltNonce = BigInt(0) + saltNonce = BigInt(0), + validators = [], + executors = [], + fallbacks = [], + hooks = [], + attesters = [], + attestersThreshold = 0 }: { client: Client owner: Address @@ -466,41 +898,48 @@ const getAccountAddress = async < }[] safeModules?: Address[] saltNonce?: bigint + erc7569LaunchpadAddress?: Address + validators?: { address: Address; context: Address }[] + executors?: { + address: Address + context: Address + }[] + fallbacks?: { address: Address; context: Address }[] + hooks?: { address: Address; context: Address }[] + attesters?: Address[] + attestersThreshold?: number }): Promise
=> { const proxyCreationCode = await readContract(client, { - abi: [ - { - inputs: [], - name: "proxyCreationCode", - outputs: [ - { - internalType: "bytes", - name: "", - type: "bytes" - } - ], - stateMutability: "pure", - type: "function" - } - ], + abi: proxyCreationCodeAbi, address: safeProxyFactoryAddress, functionName: "proxyCreationCode" }) - const deploymentCode = encodePacked( - ["bytes", "uint256"], - [proxyCreationCode, hexToBigInt(safeSingletonAddress)] - ) - const initializer = await getInitializerCode({ owner, safeModuleSetupAddress, safe4337ModuleAddress, multiSendAddress, setupTransactions, - safeModules + safeSingletonAddress, + safeModules, + erc7569LaunchpadAddress, + validators, + executors, + fallbacks, + hooks, + attesters, + attestersThreshold }) + const deploymentCode = encodePacked( + ["bytes", "uint256"], + [ + proxyCreationCode, + hexToBigInt(erc7569LaunchpadAddress ?? safeSingletonAddress) + ] + ) + const salt = keccak256( encodePacked( ["bytes32", "uint256"], @@ -577,31 +1016,66 @@ const getDefaultAddresses = ( } } +type GetErc7579Params = + TErc7579 extends undefined + ? { + safeModuleSetupAddress?: Address + multiSendAddress?: Address + multiSendCallOnlyAddress?: Address + setupTransactions?: { + to: Address + data: Address + value: bigint + }[] + safeModules?: Address[] + } + : { + validators?: { address: Address; context: Address }[] + executors?: { + address: Address + context: Address + }[] + fallbacks?: { address: Address; context: Address }[] + hooks?: { address: Address; context: Address }[] + attesters?: Address[] + attestersThreshold?: number + } + export type SignerToSafeSmartAccountParameters< entryPoint extends EntryPoint, TSource extends string = string, - TAddress extends Address = Address -> = Prettify<{ + TAddress extends Address = Address, + TErc7579 extends Address | undefined = Address | undefined +> = { signer: SmartAccountSigner safeVersion: SafeVersion entryPoint: entryPoint - address?: Address - safeModuleSetupAddress?: Address safe4337ModuleAddress?: Address + erc7569LaunchpadAddress?: TErc7579 safeProxyFactoryAddress?: Address safeSingletonAddress?: Address - multiSendAddress?: Address - multiSendCallOnlyAddress?: Address + address?: Address saltNonce?: bigint validUntil?: number validAfter?: number - setupTransactions?: { - to: Address - data: Address - value: bigint - }[] - safeModules?: Address[] -}> + nonceKey?: bigint +} & GetErc7579Params + +function isErc7579Args( + args: SignerToSafeSmartAccountParameters< + EntryPoint, + string, + Address, + Address | undefined + > +): args is SignerToSafeSmartAccountParameters< + EntryPoint, + string, + Address, + Address +> { + return args.erc7569LaunchpadAddress !== undefined +} /** * @description Creates an Simple Account from a private key. @@ -613,28 +1087,72 @@ export async function signerToSafeSmartAccount< TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined, TSource extends string = string, - TAddress extends Address = Address + TAddress extends Address = Address, + TErc7579 extends Address | undefined = undefined >( - client: Client, - { + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, + args: SignerToSafeSmartAccountParameters< + entryPoint, + TSource, + TAddress, + TErc7579 + > +): Promise> { + const chainId = client.chain?.id ?? (await getChainId(client)) + + const { signer, address, safeVersion, entryPoint: entryPointAddress, - safeModuleSetupAddress: _safeModuleSetupAddress, safe4337ModuleAddress: _safe4337ModuleAddress, safeProxyFactoryAddress: _safeProxyFactoryAddress, safeSingletonAddress: _safeSingletonAddress, - multiSendAddress: _multiSendAddress, - multiSendCallOnlyAddress: _multiSendCallOnlyAddress, + erc7569LaunchpadAddress, saltNonce = BigInt(0), validUntil = 0, validAfter = 0, - safeModules = [], - setupTransactions = [] - }: SignerToSafeSmartAccountParameters -): Promise> { - const chainId = client.chain?.id ?? (await getChainId(client)) + nonceKey + } = args + + let _safeModuleSetupAddress: Address | undefined = undefined + let _multiSendAddress: Address | undefined = undefined + let _multiSendCallOnlyAddress: Address | undefined = undefined + let safeModules: Address[] | undefined = undefined + let setupTransactions: { + to: `0x${string}` + data: `0x${string}` + value: bigint + }[] = [] + let validators: { address: Address; context: Address }[] = [] + let executors: { address: Address; context: Address }[] = [] + let fallbacks: { address: Address; context: Address }[] = [] + let hooks: { address: Address; context: Address }[] = [] + let attesters: Address[] = [] + let attestersThreshold = 0 + + if (!isErc7579Args(args)) { + _safeModuleSetupAddress = args.safeModuleSetupAddress + _multiSendAddress = args.multiSendAddress + _multiSendCallOnlyAddress = args.multiSendCallOnlyAddress + safeModules = args.safeModules + setupTransactions = args.setupTransactions ?? [] + } + + if (isErc7579Args(args)) { + validators = args.validators ?? [] + executors = args.executors ?? [] + fallbacks = args.fallbacks ?? [] + hooks = args.hooks ?? [] + attesters = args.attesters ?? [] + attestersThreshold = args.attestersThreshold ?? 0 + } const viemSigner: LocalAccount = { ...signer, @@ -669,9 +1187,16 @@ export async function signerToSafeSmartAccount< safeProxyFactoryAddress, safeSingletonAddress, multiSendAddress, + erc7569LaunchpadAddress, saltNonce, setupTransactions, - safeModules + safeModules, + validators, + executors, + fallbacks, + hooks, + attesters, + attestersThreshold })) if (!accountAddress) throw new Error("Account address not found") @@ -681,6 +1206,10 @@ export async function signerToSafeSmartAccount< const safeSmartAccount: SafeSmartAccount = toSmartAccount({ address: accountAddress, + client: client, + publicKey: accountAddress, + entryPoint: entryPointAddress, + source: "SafeSmartAccount", async signMessage({ message }) { const messageHash = hashTypedData({ domain: { @@ -736,14 +1265,11 @@ export async function signerToSafeSmartAccount< }) ) }, - client: client, - publicKey: accountAddress, - entryPoint: entryPointAddress, - source: "SafeSmartAccount", - async getNonce() { + async getNonce(key?: bigint) { return getAccountNonce(client, { sender: accountAddress, - entryPoint: entryPointAddress + entryPoint: entryPointAddress, + key: key ?? nonceKey }) }, async signUserOperation( @@ -765,10 +1291,13 @@ export async function signerToSafeSmartAccount< entryPoint: entryPointAddress } + let isDeployed = false + if ( isUserOperationVersion06(entryPointAddress, userOperation) ) { message.paymasterAndData = userOperation.paymasterAndData + isDeployed = userOperation.initCode === "0x" } if ( @@ -782,6 +1311,13 @@ export async function signerToSafeSmartAccount< } message.paymasterAndData = getPaymasterAndData(userOperation) + isDeployed = !userOperation.factory + } + + let verifyingContract = safe4337ModuleAddress + + if (erc7569LaunchpadAddress && !isDeployed) { + verifyingContract = userOperation.sender } const signatures = [ @@ -790,8 +1326,8 @@ export async function signerToSafeSmartAccount< data: await signTypedData(client, { account: viemSigner, domain: { - chainId: chainId, - verifyingContract: safe4337ModuleAddress + chainId, + verifyingContract }, types: getEntryPointVersion(entryPointAddress) === @@ -851,9 +1387,16 @@ export async function signerToSafeSmartAccount< safe4337ModuleAddress, safeSingletonAddress, multiSendAddress, + erc7569LaunchpadAddress, saltNonce, setupTransactions, - safeModules + safeModules, + validators, + executors, + fallbacks, + hooks, + attesters, + attestersThreshold }) }, async encodeDeployCallData(_) { @@ -862,12 +1405,74 @@ export async function signerToSafeSmartAccount< ) }, async encodeCallData(args) { + const isArray = Array.isArray(args) + + if (erc7569LaunchpadAddress) { + // First transaction will be slower because we need to enable 7579 modules + + safeDeployed = + safeDeployed || + (await isSmartAccountDeployed(client, accountAddress)) + + if (!safeDeployed) { + const initData = get7579LaunchPadInitData({ + safe4337ModuleAddress, + safeSingletonAddress, + erc7569LaunchpadAddress, + owner: viemSigner.address, + validators, + executors, + fallbacks, + hooks, + attesters, + attestersThreshold + }) + + return encodeFunctionData({ + abi: setupSafeAbi, + functionName: "setupSafe", + args: [ + { + ...initData, + validators: initData.validators.map( + (validator) => ({ + module: validator.address, + initData: validator.context + }) + ), + callData: encode7579CallData({ + mode: { + type: isArray + ? "batchcall" + : "call", + revertOnError: false, + selector: "0x", + context: "0x" + }, + callData: args + }) + } + ] + }) + } + + return encode7579CallData({ + mode: { + type: isArray ? "batchcall" : "call", + revertOnError: false, + selector: "0x", + context: "0x" + }, + callData: args + }) + } + let to: Address let value: bigint let data: Hex let operationType = 0 - if (Array.isArray(args)) { + if (isArray) { const argsArray = args as { to: Address value: bigint @@ -893,36 +1498,7 @@ export async function signerToSafeSmartAccount< } return encodeFunctionData({ - abi: [ - { - inputs: [ - { - internalType: "address", - name: "to", - type: "address" - }, - { - internalType: "uint256", - name: "value", - type: "uint256" - }, - { - internalType: "bytes", - name: "data", - type: "bytes" - }, - { - internalType: "uint8", - name: "operation", - type: "uint8" - } - ], - name: "executeUserOpWithErrorString", - outputs: [], - stateMutability: "nonpayable", - type: "function" - } - ], + abi: executeUserOpWithErrorStringAbi, functionName: "executeUserOpWithErrorString", args: [to, value, data, operationType] }) diff --git a/packages/permissionless/accounts/simple/privateKeyToSimpleSmartAccount.ts b/packages/permissionless/accounts/simple/privateKeyToSimpleSmartAccount.ts index a8fef7e8..3d4868b9 100644 --- a/packages/permissionless/accounts/simple/privateKeyToSimpleSmartAccount.ts +++ b/packages/permissionless/accounts/simple/privateKeyToSimpleSmartAccount.ts @@ -1,4 +1,12 @@ -import type { Address, Chain, Client, Hex, Transport } from "viem" +import type { + Address, + Chain, + Client, + Hex, + PublicActions, + PublicRpcSchema, + Transport +} from "viem" import { privateKeyToAccount } from "viem/accounts" import type { EntryPoint, Prettify } from "../../types" import { @@ -25,7 +33,13 @@ export async function privateKeyToSimpleSmartAccount< TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { privateKey, ...rest diff --git a/packages/permissionless/accounts/simple/signerToSimpleSmartAccount.ts b/packages/permissionless/accounts/simple/signerToSimpleSmartAccount.ts index 6121530a..6e571faa 100644 --- a/packages/permissionless/accounts/simple/signerToSimpleSmartAccount.ts +++ b/packages/permissionless/accounts/simple/signerToSimpleSmartAccount.ts @@ -4,6 +4,8 @@ import { type Client, type Hex, type LocalAccount, + type PublicActions, + type PublicRpcSchema, type Transport, concatHex, encodeFunctionData @@ -117,6 +119,7 @@ export type SignerToSimpleSmartAccountParameters< entryPoint: entryPoint index?: bigint address?: Address + nonceKey?: bigint }> const getFactoryAddress = ( @@ -142,13 +145,20 @@ export async function signerToSimpleSmartAccount< TSource extends string = string, TAddress extends Address = Address >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { signer, factoryAddress: _factoryAddress, entryPoint: entryPointAddress, index = BigInt(0), - address + address, + nonceKey }: SignerToSimpleSmartAccountParameters ): Promise> { const viemSigner: LocalAccount = { @@ -194,10 +204,11 @@ export async function signerToSimpleSmartAccount< publicKey: accountAddress, entryPoint: entryPointAddress, source: "SimpleSmartAccount", - async getNonce() { + async getNonce(key?: bigint) { return getAccountNonce(client, { sender: accountAddress, - entryPoint: entryPointAddress + entryPoint: entryPointAddress, + key: key ?? nonceKey }) }, async signUserOperation(userOperation) { diff --git a/packages/permissionless/accounts/toSmartAccount.ts b/packages/permissionless/accounts/toSmartAccount.ts index d797e1f5..ecf71957 100644 --- a/packages/permissionless/accounts/toSmartAccount.ts +++ b/packages/permissionless/accounts/toSmartAccount.ts @@ -6,6 +6,8 @@ import { type CustomSource, type EncodeDeployDataParameters, type Hex, + type PublicActions, + type PublicRpcSchema, type SignableMessage, type Transport, type TypedDataDefinition, @@ -48,9 +50,9 @@ export function toSmartAccount< signTypedData }: TAccountSource & { source: TSource - client: Client + client: Client entryPoint: TEntryPoint - getNonce: () => Promise + getNonce: (key?: bigint) => Promise getInitCode: () => Promise getFactory: () => Promise
getFactoryData: () => Promise @@ -163,5 +165,5 @@ export function toSmartAccount< getDummySignature, encodeDeployCallData, signUserOperation - } as SmartAccount + } } diff --git a/packages/permissionless/accounts/trust/privateKeyToTrustSmartAccount.ts b/packages/permissionless/accounts/trust/privateKeyToTrustSmartAccount.ts index f3cfe41d..9640c313 100644 --- a/packages/permissionless/accounts/trust/privateKeyToTrustSmartAccount.ts +++ b/packages/permissionless/accounts/trust/privateKeyToTrustSmartAccount.ts @@ -1,4 +1,11 @@ -import type { Chain, Client, Hex, Transport } from "viem" +import type { + Chain, + Client, + Hex, + PublicActions, + PublicRpcSchema, + Transport +} from "viem" import { privateKeyToAccount } from "viem/accounts" import type { ENTRYPOINT_ADDRESS_V06_TYPE, Prettify } from "../../types" import { @@ -25,7 +32,13 @@ export async function privateKeyToTrustSmartAccount< TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { privateKey, ...rest }: PrivateKeyToTrustSmartAccountParameters ): Promise> { const privateKeyAccount = privateKeyToAccount(privateKey) diff --git a/packages/permissionless/accounts/trust/signerToTrustSmartAccount.ts b/packages/permissionless/accounts/trust/signerToTrustSmartAccount.ts index 5330380e..9e1e112f 100644 --- a/packages/permissionless/accounts/trust/signerToTrustSmartAccount.ts +++ b/packages/permissionless/accounts/trust/signerToTrustSmartAccount.ts @@ -4,6 +4,8 @@ import { type Client, type Hex, type LocalAccount, + type PublicActions, + type PublicRpcSchema, type Transport, type TypedData, type TypedDataDefinition, @@ -86,6 +88,7 @@ export type SignerToTrustSmartAccountParameters< index?: bigint address?: Address secp256k1VerificationFacetAddress?: Address + nonceKey?: bigint } /** @@ -100,14 +103,21 @@ export async function signerToTrustSmartAccount< TSource extends string = string, TAddress extends Address = Address >( - client: Client, + client: Client< + TTransport, + TChain, + undefined, + PublicRpcSchema, + PublicActions + >, { signer, factoryAddress = TRUST_ADDRESSES.factoryAddress, entryPoint: entryPointAddress, index = 0n, secp256k1VerificationFacetAddress = TRUST_ADDRESSES.secp256k1VerificationFacetAddress, - address + address, + nonceKey }: SignerToTrustSmartAccountParameters ): Promise> { const viemSigner: LocalAccount = { @@ -164,10 +174,11 @@ export async function signerToTrustSmartAccount< hashTypedData(typedData) ) }, - getNonce: async () => { + getNonce: async (key?: bigint) => { return getAccountNonce(client, { sender: accountAddress, - entryPoint: entryPointAddress + entryPoint: entryPointAddress, + key: key ?? nonceKey }) }, signUserOperation: async (userOperation) => { diff --git a/packages/permissionless/accounts/types.ts b/packages/permissionless/accounts/types.ts index a0253ecc..263f8ab6 100644 --- a/packages/permissionless/accounts/types.ts +++ b/packages/permissionless/accounts/types.ts @@ -6,7 +6,13 @@ import { type Hex, type LocalAccount } from "viem" -import type { Chain, EncodeDeployDataParameters, Transport } from "viem" +import type { + Chain, + EncodeDeployDataParameters, + PublicActions, + PublicRpcSchema, + Transport +} from "viem" import type { UserOperation } from "../types" import type { EntryPoint, GetEntryPointVersion } from "../types/entrypoint" @@ -33,9 +39,9 @@ export type SmartAccount< chain extends Chain | undefined = Chain | undefined, TAbi extends Abi | readonly unknown[] = Abi > = LocalAccount & { - client: Client + client: Client entryPoint: entryPoint - getNonce: () => Promise + getNonce: (key?: bigint) => Promise getInitCode: () => Promise getFactory: () => Promise
getFactoryData: () => Promise diff --git a/packages/permissionless/actions/bundler/estimateUserOperationGas.ts b/packages/permissionless/actions/bundler/estimateUserOperationGas.ts index f65d2c66..00f518be 100644 --- a/packages/permissionless/actions/bundler/estimateUserOperationGas.ts +++ b/packages/permissionless/actions/bundler/estimateUserOperationGas.ts @@ -1,5 +1,5 @@ import type { Account, BaseError, Chain, Client, Hex, Transport } from "viem" -import type { PartialBy } from "viem/types/utils" +import type { PartialBy } from "viem/chains" import type { BundlerClient } from "../../clients/createBundlerClient" import type { Prettify } from "../../types/" import type { BundlerRpcSchema, StateOverrides } from "../../types/bundler" diff --git a/packages/permissionless/actions/erc7579.ts b/packages/permissionless/actions/erc7579.ts new file mode 100644 index 00000000..64bf9c7b --- /dev/null +++ b/packages/permissionless/actions/erc7579.ts @@ -0,0 +1,114 @@ +import type { Chain, Client, Hash, Transport } from "viem" +import type { SmartAccount } from "../accounts" +import type { GetAccountParameter } from "../types" +import type { EntryPoint } from "../types/entrypoint" +import { accountId } from "./erc7579/accountId" +import { + type InstallModuleParameters, + installModule +} from "./erc7579/installModule" +import { + type IsModuleInstalledParameters, + isModuleInstalled +} from "./erc7579/isModuleInstalled" +import { + type SupportsExecutionModeParameters, + supportsExecutionMode +} from "./erc7579/supportsExecutionMode" +import type { CallType, ExecutionMode } from "./erc7579/supportsExecutionMode" +import { + type SupportsModuleParameters, + supportsModule +} from "./erc7579/supportsModule" +import type { ModuleType } from "./erc7579/supportsModule" +import { + type UninstallModuleParameters, + uninstallModule +} from "./erc7579/uninstallModule" + +export type Erc7579Actions< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined +> = { + accountId: ( + args?: TSmartAccount extends undefined + ? GetAccountParameter + : undefined + ) => Promise + installModule: ( + args: InstallModuleParameters + ) => Promise + isModuleInstalled: ( + args: IsModuleInstalledParameters + ) => Promise + supportsExecutionMode: ( + args: SupportsExecutionModeParameters + ) => Promise + supportsModule: ( + args: SupportsModuleParameters + ) => Promise + uninstallModule: ( + args: UninstallModuleParameters + ) => Promise +} + +export type { + InstallModuleParameters, + IsModuleInstalledParameters, + CallType, + ExecutionMode, + SupportsExecutionModeParameters, + ModuleType, + SupportsModuleParameters, + UninstallModuleParameters +} + +export { + accountId, + installModule, + isModuleInstalled, + supportsExecutionMode, + supportsModule, + uninstallModule +} + +export function erc7579Actions(_args: { + entryPoint: TEntryPoint +}) { + return < + TSmartAccount extends SmartAccount | undefined, + TTransport extends Transport, + TChain extends Chain | undefined + >( + client: Client + ): Erc7579Actions => ({ + accountId: (args) => accountId(client, args), + installModule: (args) => + installModule( + client, + args + ), + isModuleInstalled: (args) => + isModuleInstalled( + client, + args + ), + supportsExecutionMode: (args) => + supportsExecutionMode< + TEntryPoint, + TSmartAccount, + TTransport, + TChain + >(client, args), + supportsModule: (args) => + supportsModule( + client, + args + ), + uninstallModule: (args) => + uninstallModule( + client, + args + ) + }) +} diff --git a/packages/permissionless/actions/erc7579/accountId.test.ts b/packages/permissionless/actions/erc7579/accountId.test.ts new file mode 100644 index 00000000..c50ea237 --- /dev/null +++ b/packages/permissionless/actions/erc7579/accountId.test.ts @@ -0,0 +1,52 @@ +import { zeroAddress } from "viem" +import { generatePrivateKey } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient +} from "../../../permissionless-test/src/utils" +import { ENTRYPOINT_ADDRESS_V07 } from "../../utils" +import { accountId } from "./accountId" + +describe.each(getCoreSmartAccounts())( + "accountId $name", + ({ getErc7579SmartAccountClient }) => { + testWithRpc.skipIf(!getErc7579SmartAccountClient)( + "accountId", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + if (!getErc7579SmartAccountClient) { + throw new Error("getErc7579SmartAccountClient not defined") + } + + const smartClient = await getErc7579SmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + paymasterRpc + }) + }) + + const accountIdBeforeDeploy = await accountId( + smartClient as any + ) + + // deploy account + await smartClient.sendTransaction({ + to: zeroAddress, + value: 0n, + data: "0x" + }) + + const postDeployAccountId = await accountId(smartClient as any) + + expect(accountIdBeforeDeploy).toBe(postDeployAccountId) + } + ) + } +) diff --git a/packages/permissionless/actions/erc7579/accountId.ts b/packages/permissionless/actions/erc7579/accountId.ts new file mode 100644 index 00000000..0a1210c9 --- /dev/null +++ b/packages/permissionless/actions/erc7579/accountId.ts @@ -0,0 +1,91 @@ +import { + type Chain, + type Client, + ContractFunctionExecutionError, + type Transport, + decodeFunctionResult, + encodeFunctionData +} from "viem" +import type { SmartAccount } from "../../accounts/types" +import type { GetAccountParameter } from "../../types" +import type { EntryPoint } from "../../types/entrypoint" +import { parseAccount } from "../../utils/" +import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA" + +export async function accountId< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined +>( + client: Client, + args?: TSmartAccount extends undefined + ? GetAccountParameter + : undefined +): Promise { + let account_ = client.account + + if (args) { + account_ = args.account as TSmartAccount + } + + if (!account_) { + throw new AccountOrClientNotFoundError({ + docsPath: "/docs/actions/wallet/sendTransaction" + }) + } + + const account = parseAccount(account_) as SmartAccount + + const publicClient = account.client + + const abi = [ + { + name: "accountId", + type: "function", + stateMutability: "view", + inputs: [], + outputs: [ + { + type: "string", + name: "accountImplementationId" + } + ] + } + ] as const + + try { + return await publicClient.readContract({ + abi, + functionName: "accountId", + address: account.address + }) + } catch (error) { + if (error instanceof ContractFunctionExecutionError) { + const factory = await account.getFactory() + const factoryData = await account.getFactoryData() + + const result = await publicClient.call({ + factory: factory, + factoryData: factoryData, + to: account.address, + data: encodeFunctionData({ + abi, + functionName: "accountId" + }) + }) + + if (!result || !result.data) { + throw new Error("accountId result is empty") + } + + return decodeFunctionResult({ + abi, + functionName: "accountId", + data: result.data + }) + } + + throw error + } +} diff --git a/packages/permissionless/actions/erc7579/installModule.test.ts b/packages/permissionless/actions/erc7579/installModule.test.ts new file mode 100644 index 00000000..0f00cefb --- /dev/null +++ b/packages/permissionless/actions/erc7579/installModule.test.ts @@ -0,0 +1,124 @@ +import { + http, + type Chain, + type Transport, + encodeAbiParameters, + encodePacked, + isHash, + zeroAddress +} from "viem" +import { generatePrivateKey } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient +} from "../../../permissionless-test/src/utils" +import type { SmartAccount } from "../../accounts" +import { createBundlerClient } from "../../clients/createBundlerClient" +import type { SmartAccountClient } from "../../clients/createSmartAccountClient" +import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../types/entrypoint" +import { ENTRYPOINT_ADDRESS_V07 } from "../../utils" +import { erc7579Actions } from "../erc7579" +import { installModule } from "./installModule" + +describe.each(getCoreSmartAccounts())( + "installmodule $name", + ({ getErc7579SmartAccountClient, name }) => { + testWithRpc.skipIf(!getErc7579SmartAccountClient)( + "installModule", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + if (!getErc7579SmartAccountClient) { + throw new Error("getErc7579SmartAccountClient not defined") + } + + const privateKey = generatePrivateKey() + + const smartClientWithoutExtend: SmartAccountClient< + ENTRYPOINT_ADDRESS_V07_TYPE, + Transport, + Chain, + SmartAccount + > = await getErc7579SmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + privateKey: privateKey, + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + paymasterRpc + }) + }) + + const smartClient = smartClientWithoutExtend.extend( + erc7579Actions({ + entryPoint: ENTRYPOINT_ADDRESS_V07 + }) + ) + + const moduleData = encodePacked( + ["address"], + [smartClient.account.address] + ) + + const opHash = await installModule(smartClient as any, { + account: smartClient.account as any, + type: "executor", + address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891", + context: + name === "Kernel" + ? encodePacked( + ["address", "bytes"], + [ + zeroAddress, + encodeAbiParameters( + [ + { type: "bytes" }, + { type: "bytes" } + ], + [moduleData, "0x"] + ) + ] + ) + : moduleData + }) + + const bundlerClientV07 = createBundlerClient({ + transport: http(altoRpc), + entryPoint: ENTRYPOINT_ADDRESS_V07 + }) + + expect(isHash(opHash)).toBe(true) + + const userOperationReceipt = + await bundlerClientV07.waitForUserOperationReceipt({ + hash: opHash, + timeout: 100000 + }) + expect(userOperationReceipt).not.toBeNull() + expect(userOperationReceipt?.userOpHash).toBe(opHash) + expect( + userOperationReceipt?.receipt.transactionHash + ).toBeTruthy() + + const receipt = await bundlerClientV07.getUserOperationReceipt({ + hash: opHash + }) + + expect(receipt?.receipt.transactionHash).toBe( + userOperationReceipt?.receipt.transactionHash + ) + + const isModuleInstalled = await smartClient.isModuleInstalled({ + type: "executor", + address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891", + context: "0x" + }) + + expect(isModuleInstalled).toBe(true) + } + ) + } +) diff --git a/packages/permissionless/actions/erc7579/installModule.ts b/packages/permissionless/actions/erc7579/installModule.ts new file mode 100644 index 00000000..1d38bed0 --- /dev/null +++ b/packages/permissionless/actions/erc7579/installModule.ts @@ -0,0 +1,109 @@ +import { + type Address, + type Chain, + type Client, + type Hex, + type Transport, + encodeFunctionData, + getAddress +} from "viem" +import { getAction } from "viem/utils" +import type { SmartAccount } from "../../accounts/types" +import type { GetAccountParameter, Prettify } from "../../types/" +import type { EntryPoint } from "../../types/entrypoint" +import { parseAccount } from "../../utils/" +import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA" +import type { Middleware } from "../smartAccount/prepareUserOperationRequest" +import { sendUserOperation } from "../smartAccount/sendUserOperation" +import { type ModuleType, parseModuleTypeId } from "./supportsModule" + +export type InstallModuleParameters< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined +> = GetAccountParameter & { + type: ModuleType + address: Address + context: Hex + maxFeePerGas?: bigint + maxPriorityFeePerGas?: bigint + nonce?: bigint +} & Middleware + +export async function installModule< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined +>( + client: Client, + parameters: Prettify> +): Promise { + const { + account: account_ = client.account, + maxFeePerGas, + maxPriorityFeePerGas, + nonce, + middleware, + address, + context + } = parameters + + if (!account_) { + throw new AccountOrClientNotFoundError({ + docsPath: "/docs/actions/wallet/sendTransaction" + }) + } + + const account = parseAccount(account_) as SmartAccount + + const installModuleCallData = await account.encodeCallData({ + to: account.address, + value: BigInt(0), + data: encodeFunctionData({ + abi: [ + { + name: "installModule", + type: "function", + stateMutability: "nonpayable", + inputs: [ + { + type: "uint256", + name: "moduleTypeId" + }, + { + type: "address", + name: "module" + }, + { + type: "bytes", + name: "initData" + } + ], + outputs: [] + } + ], + functionName: "installModule", + args: [ + parseModuleTypeId(parameters.type), + getAddress(address), + context + ] + }) + }) + + return getAction( + client, + sendUserOperation, + "sendUserOperation" + )({ + userOperation: { + sender: account.address, + maxFeePerGas: maxFeePerGas || BigInt(0), + maxPriorityFeePerGas: maxPriorityFeePerGas || BigInt(0), + callData: installModuleCallData, + nonce: nonce ? BigInt(nonce) : undefined + }, + account: account, + middleware + }) +} diff --git a/packages/permissionless/actions/erc7579/isModuleInstalled.test.ts b/packages/permissionless/actions/erc7579/isModuleInstalled.test.ts new file mode 100644 index 00000000..8aebdbd6 --- /dev/null +++ b/packages/permissionless/actions/erc7579/isModuleInstalled.test.ts @@ -0,0 +1,119 @@ +import { + http, + type Chain, + type Transport, + encodeAbiParameters, + encodePacked, + zeroAddress +} from "viem" +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient +} from "../../../permissionless-test/src/utils" +import type { SmartAccount } from "../../accounts" +import { createBundlerClient } from "../../clients/createBundlerClient" +import type { SmartAccountClient } from "../../clients/createSmartAccountClient" +import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../types/entrypoint" +import { ENTRYPOINT_ADDRESS_V07 } from "../../utils" +import { erc7579Actions } from "../erc7579" +import { isModuleInstalled } from "./isModuleInstalled" + +describe.each(getCoreSmartAccounts())( + "isModuleInstalled $name", + ({ getErc7579SmartAccountClient, name }) => { + testWithRpc.skipIf(!getErc7579SmartAccountClient)( + "isModuleInstalled", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + if (!getErc7579SmartAccountClient) { + throw new Error("getErc7579SmartAccountClient not defined") + } + + const privateKey = generatePrivateKey() + + const smartClientWithoutExtend: SmartAccountClient< + ENTRYPOINT_ADDRESS_V07_TYPE, + Transport, + Chain, + SmartAccount + > = await getErc7579SmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + privateKey: privateKey, + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + paymasterRpc + }) + }) + + const smartClient = smartClientWithoutExtend.extend( + erc7579Actions({ + entryPoint: ENTRYPOINT_ADDRESS_V07 + }) + ) + + const moduleData = encodePacked( + ["address"], + [smartClient.account.address] + ) + + const opHash = await smartClient.installModule({ + account: smartClient.account as any, + type: "executor", + address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891", + context: + name === "Kernel" + ? encodePacked( + ["address", "bytes"], + [ + zeroAddress, + encodeAbiParameters( + [ + { type: "bytes" }, + { type: "bytes" } + ], + [moduleData, "0x"] + ) + ] + ) + : moduleData + }) + + const bundlerClientV07 = createBundlerClient({ + transport: http(altoRpc), + entryPoint: ENTRYPOINT_ADDRESS_V07 + }) + + const receipt = + await bundlerClientV07.waitForUserOperationReceipt({ + hash: opHash, + timeout: 100000 + }) + + const isModuleInstalledResult = await isModuleInstalled( + smartClient as any, + { + account: smartClient.account as any, + type: "executor", + address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891", + context: "0x" + } + ) + + expect(isModuleInstalledResult).toBe(true) + + const nextTransaction = await smartClient.sendTransaction({ + to: zeroAddress, + value: 0n + }) + + expect(nextTransaction).toBeTruthy() + } + ) + } +) diff --git a/packages/permissionless/actions/erc7579/isModuleInstalled.ts b/packages/permissionless/actions/erc7579/isModuleInstalled.ts new file mode 100644 index 00000000..a002be39 --- /dev/null +++ b/packages/permissionless/actions/erc7579/isModuleInstalled.ts @@ -0,0 +1,122 @@ +import { + type Address, + type Chain, + type Client, + ContractFunctionExecutionError, + type Hex, + type Transport, + decodeFunctionResult, + encodeFunctionData, + getAddress +} from "viem" +import type { SmartAccount } from "../../accounts/types" +import type { GetAccountParameter } from "../../types/" +import type { EntryPoint } from "../../types/entrypoint" +import { parseAccount } from "../../utils/" +import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA" +import { type ModuleType, parseModuleTypeId } from "./supportsModule" + +export type IsModuleInstalledParameters< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined = + | SmartAccount + | undefined +> = GetAccountParameter & { + type: ModuleType + address: Address + context: Hex +} + +export async function isModuleInstalled< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined +>( + client: Client, + parameters: IsModuleInstalledParameters +): Promise { + const { account: account_ = client.account, address, context } = parameters + + if (!account_) { + throw new AccountOrClientNotFoundError({ + docsPath: "/docs/actions/wallet/sendTransaction" + }) + } + + const account = parseAccount(account_) as SmartAccount + + const publicClient = account.client + + const abi = [ + { + name: "isModuleInstalled", + type: "function", + stateMutability: "view", + inputs: [ + { + type: "uint256", + name: "moduleTypeId" + }, + { + type: "address", + name: "module" + }, + { + type: "bytes", + name: "additionalContext" + } + ], + outputs: [ + { + type: "bool" + } + ] + } + ] as const + + try { + return await publicClient.readContract({ + abi, + functionName: "isModuleInstalled", + args: [ + parseModuleTypeId(parameters.type), + getAddress(address), + context + ], + address: account.address + }) + } catch (error) { + if (error instanceof ContractFunctionExecutionError) { + const factory = await account.getFactory() + const factoryData = await account.getFactoryData() + + const result = await publicClient.call({ + factory: factory, + factoryData: factoryData, + to: account.address, + data: encodeFunctionData({ + abi, + functionName: "isModuleInstalled", + args: [ + parseModuleTypeId(parameters.type), + getAddress(address), + context + ] + }) + }) + + if (!result || !result.data) { + throw new Error("accountId result is empty") + } + + return decodeFunctionResult({ + abi, + functionName: "isModuleInstalled", + data: result.data + }) + } + + throw error + } +} diff --git a/packages/permissionless/actions/erc7579/supportsExecutionMode.test.ts b/packages/permissionless/actions/erc7579/supportsExecutionMode.test.ts new file mode 100644 index 00000000..df2637dd --- /dev/null +++ b/packages/permissionless/actions/erc7579/supportsExecutionMode.test.ts @@ -0,0 +1,72 @@ +import { zeroAddress } from "viem" +import { generatePrivateKey } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient +} from "../../../permissionless-test/src/utils" +import { ENTRYPOINT_ADDRESS_V07 } from "../../utils" +import { supportsExecutionMode } from "./supportsExecutionMode" + +describe.each(getCoreSmartAccounts())( + "supportsExecutionMode $name", + ({ getErc7579SmartAccountClient }) => { + testWithRpc.skipIf(!getErc7579SmartAccountClient)( + "supportsExecutionMode", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + if (!getErc7579SmartAccountClient) { + throw new Error("getErc7579SmartAccountClient not defined") + } + + const smartClient = await getErc7579SmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + paymasterRpc + }) + }) + + const supportsExecutionModeBatchCallBeforeDeploy = + await supportsExecutionMode(smartClient as any, { + account: smartClient.account as any, + type: "batchcall", + revertOnError: false, + selector: "0x0", + context: "0x" + }) + + expect(supportsExecutionModeBatchCallBeforeDeploy).toBe(true) + + // deploy account + await smartClient.sendTransaction({ + to: zeroAddress, + value: 0n, + data: "0x" + }) + + const supportsExecutionModeBatchCallBeforeDeployPostDeploy = + await supportsExecutionMode(smartClient as any, { + account: smartClient.account as any, + type: "batchcall", + revertOnError: false, + selector: "0x0", + context: "0x" + }) + + expect( + supportsExecutionModeBatchCallBeforeDeployPostDeploy + ).toBe(true) + + expect(supportsExecutionModeBatchCallBeforeDeploy).toBe( + supportsExecutionModeBatchCallBeforeDeployPostDeploy + ) + } + ) + } +) diff --git a/packages/permissionless/actions/erc7579/supportsExecutionMode.ts b/packages/permissionless/actions/erc7579/supportsExecutionMode.ts new file mode 100644 index 00000000..b204d2ea --- /dev/null +++ b/packages/permissionless/actions/erc7579/supportsExecutionMode.ts @@ -0,0 +1,154 @@ +import { + type Chain, + type Client, + ContractFunctionExecutionError, + type Hex, + type Transport, + decodeFunctionResult, + encodeFunctionData, + encodePacked, + toBytes, + toHex +} from "viem" +import type { SmartAccount } from "../../accounts/types" +import type { GetAccountParameter, Prettify } from "../../types/" +import type { EntryPoint } from "../../types/entrypoint" +import { parseAccount } from "../../utils/" +import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA" + +export type CallType = "call" | "delegatecall" | "batchcall" + +export type ExecutionMode = { + type: callType + revertOnError: boolean + selector: Hex + context: Hex +} + +export type SupportsExecutionModeParameters< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined = + | SmartAccount + | undefined, + callType extends CallType = CallType +> = GetAccountParameter & ExecutionMode + +function parseCallType(executionMode: CallType) { + switch (executionMode) { + case "call": + return "0x00" + case "delegatecall": + return "0x01" + case "batchcall": + return "0xff" + } +} + +export function encodeExecutionMode({ + type, + revertOnError, + selector, + context +}: ExecutionMode): Hex { + return encodePacked( + ["bytes1", "bytes1", "bytes4", "bytes4", "bytes22"], + [ + toHex(toBytes(parseCallType(type), { size: 1 })), + toHex(toBytes(revertOnError ? "0x01" : "0x00", { size: 1 })), + toHex(toBytes("0x0", { size: 4 })), + toHex(toBytes(selector, { size: 4 })), + toHex(toBytes(context, { size: 22 })) + ] + ) +} + +export async function supportsExecutionMode< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined +>( + client: Client, + args: Prettify> +): Promise { + const { + account: account_ = client.account, + type, + revertOnError, + selector, + context + } = args + + if (!account_) { + throw new AccountOrClientNotFoundError({ + docsPath: "/docs/actions/wallet/sendTransaction" + }) + } + + const account = parseAccount(account_) as SmartAccount + + const publicClient = account.client + + const encodedMode = encodeExecutionMode({ + type, + revertOnError, + selector, + context + }) + + const abi = [ + { + name: "supportsExecutionMode", + type: "function", + stateMutability: "view", + inputs: [ + { + type: "bytes32", + name: "encodedMode" + } + ], + outputs: [ + { + type: "bool" + } + ] + } + ] as const + + try { + return await publicClient.readContract({ + abi, + functionName: "supportsExecutionMode", + args: [encodedMode], + address: account.address + }) + } catch (error) { + if (error instanceof ContractFunctionExecutionError) { + const factory = await account.getFactory() + const factoryData = await account.getFactoryData() + + const result = await publicClient.call({ + factory: factory, + factoryData: factoryData, + to: account.address, + data: encodeFunctionData({ + abi, + functionName: "supportsExecutionMode", + args: [encodedMode] + }) + }) + + if (!result || !result.data) { + throw new Error("accountId result is empty") + } + + return decodeFunctionResult({ + abi, + functionName: "supportsExecutionMode", + data: result.data + }) + } + + throw error + } +} diff --git a/packages/permissionless/actions/erc7579/supportsModule.test.ts b/packages/permissionless/actions/erc7579/supportsModule.test.ts new file mode 100644 index 00000000..a246954d --- /dev/null +++ b/packages/permissionless/actions/erc7579/supportsModule.test.ts @@ -0,0 +1,46 @@ +import { generatePrivateKey } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient +} from "../../../permissionless-test/src/utils" +import { ENTRYPOINT_ADDRESS_V07 } from "../../utils" +import { supportsModule } from "./supportsModule" + +describe.each(getCoreSmartAccounts())( + "supportsModule $name", + ({ getErc7579SmartAccountClient }) => { + testWithRpc.skipIf(!getErc7579SmartAccountClient)( + "supportsModule", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + if (!getErc7579SmartAccountClient) { + throw new Error("getErc7579SmartAccountClient not defined") + } + + const smartClient = await getErc7579SmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + paymasterRpc + }) + }) + + const supportsValidationModule = await supportsModule( + smartClient as any, + { + account: smartClient.account as any, + type: "validator" + } + ) + + expect(supportsValidationModule).toBe(true) + } + ) + } +) diff --git a/packages/permissionless/actions/erc7579/supportsModule.ts b/packages/permissionless/actions/erc7579/supportsModule.ts new file mode 100644 index 00000000..489789c4 --- /dev/null +++ b/packages/permissionless/actions/erc7579/supportsModule.ts @@ -0,0 +1,117 @@ +import { + type Chain, + type Client, + ContractFunctionExecutionError, + type Transport, + decodeFunctionResult, + encodeFunctionData +} from "viem" +import type { SmartAccount } from "../../accounts/types" +import type { GetAccountParameter, Prettify } from "../../types/" +import type { EntryPoint } from "../../types/entrypoint" +import { parseAccount } from "../../utils/" +import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA" + +export type ModuleType = "validator" | "executor" | "fallback" | "hook" + +export type SupportsModuleParameters< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined = + | SmartAccount + | undefined +> = GetAccountParameter & { + type: ModuleType +} + +export function parseModuleTypeId(type: ModuleType): bigint { + switch (type) { + case "validator": + return BigInt(1) + case "executor": + return BigInt(2) + case "fallback": + return BigInt(3) + case "hook": + return BigInt(4) + default: + throw new Error("Invalid module type") + } +} + +export async function supportsModule< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined +>( + client: Client, + args: Prettify> +): Promise { + const { account: account_ = client.account } = args + + if (!account_) { + throw new AccountOrClientNotFoundError({ + docsPath: "/docs/actions/wallet/sendTransaction" + }) + } + + const account = parseAccount(account_) as SmartAccount + + const publicClient = account.client + + const abi = [ + { + name: "supportsModule", + type: "function", + stateMutability: "view", + inputs: [ + { + type: "uint256", + name: "moduleTypeId" + } + ], + outputs: [ + { + type: "bool" + } + ] + } + ] as const + + try { + return await publicClient.readContract({ + abi, + functionName: "supportsModule", + args: [parseModuleTypeId(args.type)], + address: account.address + }) + } catch (error) { + if (error instanceof ContractFunctionExecutionError) { + const factory = await account.getFactory() + const factoryData = await account.getFactoryData() + + const result = await publicClient.call({ + factory: factory, + factoryData: factoryData, + to: account.address, + data: encodeFunctionData({ + abi, + functionName: "supportsModule", + args: [parseModuleTypeId(args.type)] + }) + }) + + if (!result || !result.data) { + throw new Error("accountId result is empty") + } + + return decodeFunctionResult({ + abi, + functionName: "supportsModule", + data: result.data + }) + } + + throw error + } +} diff --git a/packages/permissionless/actions/erc7579/uninstallModule.test.ts b/packages/permissionless/actions/erc7579/uninstallModule.test.ts new file mode 100644 index 00000000..2414394c --- /dev/null +++ b/packages/permissionless/actions/erc7579/uninstallModule.test.ts @@ -0,0 +1,158 @@ +import { + http, + type Chain, + type Transport, + encodeAbiParameters, + encodePacked, + isHash, + zeroAddress +} from "viem" +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient, + getPublicClient +} from "../../../permissionless-test/src/utils" +import type { SmartAccount } from "../../accounts" +import { createBundlerClient } from "../../clients/createBundlerClient" +import type { SmartAccountClient } from "../../clients/createSmartAccountClient" +import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../types" +import { ENTRYPOINT_ADDRESS_V07 } from "../../utils" +import { erc7579Actions } from "../erc7579" +import { uninstallModule } from "./uninstallModule" + +describe.each(getCoreSmartAccounts())( + "uninstallModule $name", + ({ getErc7579SmartAccountClient, name }) => { + testWithRpc.skipIf(!getErc7579SmartAccountClient)( + "uninstallModule", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + if (!getErc7579SmartAccountClient) { + throw new Error("getErc7579SmartAccountClient not defined") + } + + const privateKey = generatePrivateKey() + + const eoaAccount = privateKeyToAccount(privateKey) + + const smartClientWithoutExtend: SmartAccountClient< + ENTRYPOINT_ADDRESS_V07_TYPE, + Transport, + Chain, + SmartAccount + > = await getErc7579SmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + privateKey: privateKey, + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V07, + paymasterRpc + }) + }) + + const smartClient = smartClientWithoutExtend.extend( + erc7579Actions({ + entryPoint: ENTRYPOINT_ADDRESS_V07 + }) + ) + + const moduleData = encodePacked( + ["address"], + [smartClient.account.address] + ) + + const bundlerClientV07 = createBundlerClient({ + transport: http(altoRpc), + entryPoint: ENTRYPOINT_ADDRESS_V07 + }) + + const publicClient = getPublicClient(anvilRpc) + + const opHash = await smartClient.installModule({ + type: "executor", + address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891", + context: + name === "Kernel" + ? encodePacked( + ["address", "bytes"], + [ + zeroAddress, + encodeAbiParameters( + [ + { type: "bytes" }, + { type: "bytes" } + ], + [moduleData, "0x"] + ) + ] + ) + : moduleData + }) + + const userOperationReceipt = + await bundlerClientV07.waitForUserOperationReceipt({ + hash: opHash, + timeout: 100000 + }) + + await publicClient.waitForTransactionReceipt({ + hash: userOperationReceipt.receipt.transactionHash + }) + + const uninstallModuleUserOpHash = await uninstallModule( + smartClient as any, + { + account: smartClient.account as any, + type: "executor", + address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891", + context: + name === "Kernel" + ? "0x" + : encodeAbiParameters( + [ + { name: "prev", type: "address" }, + { + name: "moduleInitData", + type: "bytes" + } + ], + [ + "0x0000000000000000000000000000000000000001", + "0x" + ] + ) + } + ) + + expect(isHash(uninstallModuleUserOpHash)).toBe(true) + + const userOperationReceiptUninstallModule = + await bundlerClientV07.waitForUserOperationReceipt({ + hash: uninstallModuleUserOpHash, + timeout: 100000 + }) + expect(userOperationReceiptUninstallModule).not.toBeNull() + expect(userOperationReceiptUninstallModule?.userOpHash).toBe( + uninstallModuleUserOpHash + ) + expect( + userOperationReceiptUninstallModule?.receipt.transactionHash + ).toBeTruthy() + + const receiptUninstallModule = + await bundlerClientV07.getUserOperationReceipt({ + hash: uninstallModuleUserOpHash + }) + + expect(receiptUninstallModule?.receipt.transactionHash).toBe( + userOperationReceiptUninstallModule?.receipt.transactionHash + ) + } + ) + } +) diff --git a/packages/permissionless/actions/erc7579/uninstallModule.ts b/packages/permissionless/actions/erc7579/uninstallModule.ts new file mode 100644 index 00000000..b9283f03 --- /dev/null +++ b/packages/permissionless/actions/erc7579/uninstallModule.ts @@ -0,0 +1,113 @@ +import { + type Address, + type Chain, + type Client, + type Hex, + type Transport, + encodeFunctionData, + getAddress +} from "viem" +import { getAction } from "viem/utils" +import type { SmartAccount } from "../../accounts/types" +import type { GetAccountParameter, Prettify } from "../../types/" +import type { EntryPoint } from "../../types/entrypoint" +import { parseAccount } from "../../utils/" +import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA" +import type { Middleware } from "../smartAccount/prepareUserOperationRequest" +import { sendUserOperation } from "../smartAccount/sendUserOperation" +import { type ModuleType, parseModuleTypeId } from "./supportsModule" + +export type UninstallModuleParameters< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined = + | SmartAccount + | undefined +> = GetAccountParameter & { + type: ModuleType + address: Address + context: Hex + maxFeePerGas?: bigint + maxPriorityFeePerGas?: bigint + nonce?: bigint +} & Middleware + +export async function uninstallModule< + TEntryPoint extends EntryPoint, + TSmartAccount extends SmartAccount | undefined = + | SmartAccount + | undefined, + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined +>( + client: Client, + parameters: Prettify> +): Promise { + const { + account: account_ = client.account, + maxFeePerGas, + maxPriorityFeePerGas, + nonce, + middleware, + address, + context + } = parameters + + if (!account_) { + throw new AccountOrClientNotFoundError({ + docsPath: "/docs/actions/wallet/sendTransaction" + }) + } + + const account = parseAccount(account_) as SmartAccount + + const uninstallModuleCallData = await account.encodeCallData({ + to: account.address, + value: BigInt(0), + data: encodeFunctionData({ + abi: [ + { + name: "uninstallModule", + type: "function", + stateMutability: "nonpayable", + inputs: [ + { + type: "uint256", + name: "moduleTypeId" + }, + { + type: "address", + name: "module" + }, + { + type: "bytes", + name: "deInitData" + } + ], + outputs: [] + } + ], + functionName: "uninstallModule", + args: [ + parseModuleTypeId(parameters.type), + getAddress(address), + context + ] + }) + }) + + return getAction( + client, + sendUserOperation, + "sendUserOperation" + )({ + userOperation: { + sender: account.address, + maxFeePerGas: maxFeePerGas || BigInt(0), + maxPriorityFeePerGas: maxPriorityFeePerGas || BigInt(0), + callData: uninstallModuleCallData, + nonce: nonce ? BigInt(nonce) : undefined + }, + account: account, + middleware + }) +} diff --git a/packages/permissionless/actions/index.test.ts b/packages/permissionless/actions/index.test.ts new file mode 100644 index 00000000..4e992fd3 --- /dev/null +++ b/packages/permissionless/actions/index.test.ts @@ -0,0 +1,329 @@ +import type { + Account, + Address, + Chain, + Client, + Hash, + Hex, + Log, + Transport +} from "viem" +import type { PartialBy } from "viem/chains" +import { describe, expectTypeOf, test } from "vitest" +import type { BundlerRpcSchema } from "../types/bundler" +import type { + ENTRYPOINT_ADDRESS_V06_TYPE, + ENTRYPOINT_ADDRESS_V07_TYPE, + EntryPoint +} from "../types/entrypoint" +import type { TStatus, UserOperation } from "../types/userOperation" +import { + chainId, + estimateUserOperationGas, + getAccountNonce, + getSenderAddress, + getUserOperationByHash, + getUserOperationReceipt, + sendUserOperation, + supportedEntryPoints, + waitForUserOperationReceipt +} from "./index" + +describe("index", () => { + test("sendUserOperation", () => { + expectTypeOf(sendUserOperation).toBeFunction() + expectTypeOf(sendUserOperation) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + expectTypeOf(sendUserOperation).parameter(1).toMatchTypeOf<{ + userOperation: UserOperation<"v0.6" | "v0.7"> + entryPoint: EntryPoint + }>() + expectTypeOf(sendUserOperation).returns.toMatchTypeOf>() + }) + + test("estimateUserOperationGas", () => { + expectTypeOf(estimateUserOperationGas).toBeFunction() + expectTypeOf(estimateUserOperationGas) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + + expectTypeOf(estimateUserOperationGas).parameter(1).toMatchTypeOf<{ + userOperation: + | PartialBy< + UserOperation<"v0.6">, + | "callGasLimit" + | "preVerificationGas" + | "verificationGasLimit" + > + | PartialBy< + UserOperation<"v0.7">, + | "callGasLimit" + | "preVerificationGas" + | "verificationGasLimit" + | "paymasterVerificationGasLimit" + | "paymasterPostOpGasLimit" + > + entryPoint: EntryPoint + }>() + expectTypeOf(estimateUserOperationGas).parameter(2).toMatchTypeOf< + | { + [x: string]: { + balance?: bigint | undefined + nonce?: bigint | number | undefined + code?: Hex | undefined + state?: { + [x: Hex]: Hex + } + stateDiff?: { + [x: Hex]: Hex + } + } + } + | undefined + >() + expectTypeOf( + estimateUserOperationGas + ).returns.toMatchTypeOf< + Promise<{ + preVerificationGas: bigint + verificationGasLimit: bigint + callGasLimit: bigint + }> + >() + expectTypeOf( + estimateUserOperationGas + ).returns.toMatchTypeOf< + Promise<{ + preVerificationGas: bigint + verificationGasLimit: bigint + callGasLimit: bigint + paymasterVerificationGasLimit?: bigint + paymasterPostOpGasLimit?: bigint + }> + >() + }) + + test("supportedEntryPoints", () => { + expectTypeOf(supportedEntryPoints) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + + expectTypeOf(supportedEntryPoints).returns.toMatchTypeOf< + Promise + >() + }) + + test("chainId", () => { + expectTypeOf(chainId) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + + expectTypeOf(chainId).returns.toMatchTypeOf>() + }) + + test("getUserOperationByHash", () => { + expectTypeOf(getUserOperationByHash) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + expectTypeOf(getUserOperationByHash).parameter(1).toMatchTypeOf<{ + hash: Hash + }>() + expectTypeOf( + getUserOperationByHash + ).returns.toMatchTypeOf< + Promise<{ + userOperation: UserOperation<"v0.6"> + entryPoint: Address + transactionHash: Hash + blockHash: Hash + blockNumber: bigint + } | null> + >() + expectTypeOf( + getUserOperationByHash + ).returns.toMatchTypeOf< + Promise<{ + userOperation: UserOperation<"v0.7"> + entryPoint: Address + transactionHash: Hash + blockHash: Hash + blockNumber: bigint + } | null> + >() + }) + + test("getUserOperationReceipt", () => { + expectTypeOf(getUserOperationReceipt) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + expectTypeOf(getUserOperationReceipt).parameter(1).toMatchTypeOf<{ + hash: Hash + }>() + expectTypeOf(getUserOperationReceipt).returns.toMatchTypeOf< + Promise<{ + userOpHash: Hash + entryPoint: Address + sender: Address + nonce: bigint + paymaster?: Address + actualGasUsed: bigint + actualGasCost: bigint + success: boolean + reason?: string + receipt: { + transactionHash: Hex + transactionIndex: bigint + blockHash: Hash + blockNumber: bigint + from: Address + to: Address | null + cumulativeGasUsed: bigint + status: TStatus + gasUsed: bigint + contractAddress: Address | null + logsBloom: Hex + effectiveGasPrice: bigint + } + logs: Log[] + } | null> + >() + }) + + test("getSenderAddress", () => { + expectTypeOf(getSenderAddress) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + expectTypeOf(getSenderAddress) + .parameter(1) + .toMatchTypeOf<{ + initCode: Hex + entryPoint: ENTRYPOINT_ADDRESS_V06_TYPE + factory?: never + factoryData?: never + }>() + expectTypeOf(getSenderAddress) + .parameter(1) + .toMatchTypeOf<{ + entryPoint: ENTRYPOINT_ADDRESS_V07_TYPE + factory: Address + factoryData: Hex + initCode?: never + }>() + expectTypeOf(getSenderAddress).returns.toMatchTypeOf>() + }) + + test("getAccountNonce", () => { + expectTypeOf(getAccountNonce) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + expectTypeOf(getAccountNonce).parameter(1).toMatchTypeOf<{ + sender: Address + entryPoint: EntryPoint + key?: bigint + }>() + expectTypeOf(getAccountNonce).returns.toMatchTypeOf>() + }) + + test("waitForUserOperationReceipt", () => { + expectTypeOf(waitForUserOperationReceipt) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + BundlerRpcSchema + > + >() + expectTypeOf(waitForUserOperationReceipt).parameter(1).toMatchTypeOf<{ + hash: Hash + pollingInterval?: number + timeout?: number + }>() + expectTypeOf(waitForUserOperationReceipt).returns.toMatchTypeOf< + Promise<{ + userOpHash: Hash + entryPoint: Address + sender: Address + nonce: bigint + paymaster?: Address + actualGasUsed: bigint + actualGasCost: bigint + success: boolean + reason?: string + receipt: { + transactionHash: Hex + transactionIndex: bigint + blockHash: Hash + blockNumber: bigint + from: Address + to: Address | null + cumulativeGasUsed: bigint + status: TStatus + gasUsed: bigint + contractAddress: Address | null + logsBloom: Hex + effectiveGasPrice: bigint + } + logs: Log[] + }> + >() + }) +}) diff --git a/packages/permissionless/actions/pimlico.test.ts b/packages/permissionless/actions/pimlico.test.ts new file mode 100644 index 00000000..f6d088cf --- /dev/null +++ b/packages/permissionless/actions/pimlico.test.ts @@ -0,0 +1,222 @@ +import type { + Account, + Address, + Chain, + Client, + Hash, + Hex, + Transport +} from "viem" +import { describe, expectTypeOf, test } from "vitest" +import type { EntryPoint } from "../types/entrypoint" +import type { PimlicoBundlerRpcSchema } from "../types/pimlico" +import type { UserOperation } from "../types/userOperation" +import { + type PimlicoBundlerActions, + getUserOperationGasPrice, + getUserOperationStatus, + pimlicoBundlerActions, + sendCompressedUserOperation, + sponsorUserOperation, + validateSponsorshipPolicies +} from "./pimlico" + +describe("pimlico", () => { + test("getUserOperationGasPrice", () => { + expectTypeOf(getUserOperationGasPrice).toBeFunction() + expectTypeOf(getUserOperationGasPrice) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + PimlicoBundlerRpcSchema + > + >() + expectTypeOf(getUserOperationGasPrice).returns.toMatchTypeOf | null>() + }) + + test("getUserOperationStatus", () => { + expectTypeOf(getUserOperationStatus).toBeFunction() + expectTypeOf(getUserOperationStatus) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + PimlicoBundlerRpcSchema + > + >() + expectTypeOf(getUserOperationStatus).parameter(1).toMatchTypeOf<{ + hash: string + }>() + expectTypeOf(getUserOperationStatus).returns.toMatchTypeOf< + Promise<{ + status: + | "not_found" + | "not_submitted" + | "submitted" + | "rejected" + | "reverted" + | "included" + | "failed" + transactionHash: Hash | null + }> + >() + }) + + test("sendCompressedUserOperation", () => { + expectTypeOf(sendCompressedUserOperation).toBeFunction() + expectTypeOf(sendCompressedUserOperation) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + PimlicoBundlerRpcSchema + > + >() + expectTypeOf(sendCompressedUserOperation).parameter(1).toMatchTypeOf<{ + compressedUserOperation: Hex + inflatorAddress: Address + entryPoint: Address + }>() + expectTypeOf(sendCompressedUserOperation).returns.toMatchTypeOf< + Promise + >() + }) + + test("sponsorUserOperation", () => { + expectTypeOf(sponsorUserOperation).toBeFunction() + expectTypeOf(sponsorUserOperation) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + PimlicoBundlerRpcSchema + > + >() + expectTypeOf(sponsorUserOperation).parameter(1).toMatchTypeOf<{ + userOperation: UserOperation<"v0.6" | "v0.7"> + entryPoint: EntryPoint + sponsorshipPolicyId?: string + }>() + expectTypeOf(sponsorUserOperation).returns.toMatchTypeOf< + Promise< + | { + callGasLimit: bigint + verificationGasLimit: bigint + preVerificationGas: bigint + paymasterAndData: Hex + } + | { + callGasLimit: bigint + verificationGasLimit: bigint + preVerificationGas: bigint + paymaster: Address + paymasterVerificationGasLimit: bigint + paymasterPostOpGasLimit: bigint + paymasterData: Hex + } + > + >() + }) + + test("sponsorUserOperation", () => { + expectTypeOf(sponsorUserOperation).toBeFunction() + expectTypeOf(sponsorUserOperation) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + PimlicoBundlerRpcSchema + > + >() + expectTypeOf(sponsorUserOperation).parameter(1).toMatchTypeOf<{ + userOperation: UserOperation<"v0.6" | "v0.7"> + entryPoint: EntryPoint + sponsorshipPolicyId?: string + }>() + expectTypeOf(sponsorUserOperation).returns.toMatchTypeOf< + Promise< + | { + callGasLimit: bigint + verificationGasLimit: bigint + preVerificationGas: bigint + paymasterAndData: Hex + } + | { + callGasLimit: bigint + verificationGasLimit: bigint + preVerificationGas: bigint + paymaster: Address + paymasterVerificationGasLimit: bigint + paymasterPostOpGasLimit: bigint + paymasterData: Hex + } + > + >() + }) + + test("validateSponsorshipPolicies", () => { + expectTypeOf(validateSponsorshipPolicies).toBeFunction() + expectTypeOf(validateSponsorshipPolicies) + .parameter(0) + .toMatchTypeOf< + Client< + Transport, + Chain | undefined, + Account | undefined, + PimlicoBundlerRpcSchema + > + >() + expectTypeOf(validateSponsorshipPolicies).parameter(1).toMatchTypeOf<{ + userOperation: UserOperation<"v0.6" | "v0.7"> + entryPoint: EntryPoint + sponsorshipPolicyIds: string[] + }>() + expectTypeOf(validateSponsorshipPolicies).returns.toMatchTypeOf< + Promise< + { + sponsorshipPolicyId: string + data: { + name: string | null + author: string | null + icon: string | null + description: string | null + } + }[] + > + >() + }) + + test("pimlicoBundlerActions", () => { + expectTypeOf(pimlicoBundlerActions).toBeFunction() + expectTypeOf(pimlicoBundlerActions) + .parameter(0) + .toMatchTypeOf() + expectTypeOf(pimlicoBundlerActions).returns.toMatchTypeOf< + (client: Client) => PimlicoBundlerActions + >() + }) +}) diff --git a/packages/permissionless/actions/smartAccount/signMessage.test.ts b/packages/permissionless/actions/smartAccount/signMessage.test.ts new file mode 100644 index 00000000..ecdc6eb8 --- /dev/null +++ b/packages/permissionless/actions/smartAccount/signMessage.test.ts @@ -0,0 +1,89 @@ +import type { Chain, Client, Transport } from "viem" +import { generatePrivateKey } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient, + getPublicClient +} from "../../../permissionless-test/src/utils" +import type { SmartAccount } from "../../accounts" +import type { EntryPoint } from "../../types/entrypoint" +import { ENTRYPOINT_ADDRESS_V06 } from "../../utils" +import { signMessage } from "./signMessage" + +describe.each(getCoreSmartAccounts())( + "signMessage $name", + ({ getSmartAccountClient, isEip1271Compliant }) => { + testWithRpc.skipIf(isEip1271Compliant)( + "not isEip1271Compliant", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + const smartClient = await getSmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + paymasterRpc + }) + }) + + await expect(async () => + signMessage( + smartClient as Client< + Transport, + Chain, + SmartAccount + >, + { + message: + "slowly and steadily burning the private keys" + } + ) + ).rejects.toThrow() + } + ) + + testWithRpc.skipIf(!isEip1271Compliant)( + "isEip1271Compliant", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + const smartClient = await getSmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + paymasterRpc + }) + }) + + const signature = await signMessage( + smartClient as Client< + Transport, + Chain, + SmartAccount + >, + { + message: "slowly and steadily burning the private keys" + } + ) + + const publicClient = getPublicClient(anvilRpc) + + const isVerified = await publicClient.verifyMessage({ + address: smartClient.account.address, + message: "slowly and steadily burning the private keys", + signature + }) + + expect(isVerified).toBeTruthy() + } + ) + } +) diff --git a/packages/permissionless/actions/smartAccount/signTypedData.test.ts b/packages/permissionless/actions/smartAccount/signTypedData.test.ts new file mode 100644 index 00000000..ef2be0c5 --- /dev/null +++ b/packages/permissionless/actions/smartAccount/signTypedData.test.ts @@ -0,0 +1,118 @@ +import { type Chain, type Client, type Transport, getAddress } from "viem" +import { generatePrivateKey } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient, + getPublicClient +} from "../../../permissionless-test/src/utils" +import type { SmartAccount } from "../../accounts" +import type { EntryPoint } from "../../types/entrypoint" +import { ENTRYPOINT_ADDRESS_V06 } from "../../utils" +import { signTypedData } from "./signTypedData" + +const typedData = { + domain: { + name: "Ether Mail", + version: "1", + chainId: 1, + verifyingContract: getAddress( + "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + ) + }, + types: { + Person: [ + { name: "name", type: "string" }, + { name: "wallet", type: "address" } + ], + Mail: [ + { name: "from", type: "Person" }, + { name: "to", type: "Person" }, + { name: "contents", type: "string" } + ] + }, + primaryType: "Mail" as const, + message: { + from: { + name: "Cow", + wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + to: { + name: "Bob", + wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + contents: "Hello, Bob!" + } +} + +describe.each(getCoreSmartAccounts())( + "signTypedData $name", + ({ getSmartAccountClient, isEip1271Compliant }) => { + testWithRpc.skipIf(isEip1271Compliant)( + "not isEip1271Compliant", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + const smartClient = await getSmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + paymasterRpc + }) + }) + + await expect(async () => + signTypedData( + smartClient as Client< + Transport, + Chain, + SmartAccount + >, + typedData + ) + ).rejects.toThrow() + } + ) + + testWithRpc.skipIf(!isEip1271Compliant)( + "isEip1271Compliant", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + const smartClient = await getSmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + paymasterRpc + }) + }) + + const signature = await signTypedData( + smartClient as Client< + Transport, + Chain, + SmartAccount + >, + typedData + ) + + const publicClient = getPublicClient(anvilRpc) + + const isVerified = await publicClient.verifyTypedData({ + ...typedData, + address: smartClient.account.address, + signature + }) + + expect(isVerified).toBeTruthy() + } + ) + } +) diff --git a/packages/permissionless/actions/smartAccount/writeContract.test.ts b/packages/permissionless/actions/smartAccount/writeContract.test.ts new file mode 100644 index 00000000..ef2be0c5 --- /dev/null +++ b/packages/permissionless/actions/smartAccount/writeContract.test.ts @@ -0,0 +1,118 @@ +import { type Chain, type Client, type Transport, getAddress } from "viem" +import { generatePrivateKey } from "viem/accounts" +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { + getCoreSmartAccounts, + getPimlicoPaymasterClient, + getPublicClient +} from "../../../permissionless-test/src/utils" +import type { SmartAccount } from "../../accounts" +import type { EntryPoint } from "../../types/entrypoint" +import { ENTRYPOINT_ADDRESS_V06 } from "../../utils" +import { signTypedData } from "./signTypedData" + +const typedData = { + domain: { + name: "Ether Mail", + version: "1", + chainId: 1, + verifyingContract: getAddress( + "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + ) + }, + types: { + Person: [ + { name: "name", type: "string" }, + { name: "wallet", type: "address" } + ], + Mail: [ + { name: "from", type: "Person" }, + { name: "to", type: "Person" }, + { name: "contents", type: "string" } + ] + }, + primaryType: "Mail" as const, + message: { + from: { + name: "Cow", + wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + to: { + name: "Bob", + wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + contents: "Hello, Bob!" + } +} + +describe.each(getCoreSmartAccounts())( + "signTypedData $name", + ({ getSmartAccountClient, isEip1271Compliant }) => { + testWithRpc.skipIf(isEip1271Compliant)( + "not isEip1271Compliant", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + const smartClient = await getSmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + paymasterRpc + }) + }) + + await expect(async () => + signTypedData( + smartClient as Client< + Transport, + Chain, + SmartAccount + >, + typedData + ) + ).rejects.toThrow() + } + ) + + testWithRpc.skipIf(!isEip1271Compliant)( + "isEip1271Compliant", + async ({ rpc }) => { + const { anvilRpc, altoRpc, paymasterRpc } = rpc + + const smartClient = await getSmartAccountClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + privateKey: generatePrivateKey(), + altoRpc: altoRpc, + anvilRpc: anvilRpc, + paymasterClient: getPimlicoPaymasterClient({ + entryPoint: ENTRYPOINT_ADDRESS_V06, + paymasterRpc + }) + }) + + const signature = await signTypedData( + smartClient as Client< + Transport, + Chain, + SmartAccount + >, + typedData + ) + + const publicClient = getPublicClient(anvilRpc) + + const isVerified = await publicClient.verifyTypedData({ + ...typedData, + address: smartClient.account.address, + signature + }) + + expect(isVerified).toBeTruthy() + } + ) + } +) diff --git a/packages/permissionless/package.json b/packages/permissionless/package.json index a52850e7..e2ff2674 100644 --- a/packages/permissionless/package.json +++ b/packages/permissionless/package.json @@ -29,6 +29,11 @@ "import": "./_esm/actions/index.js", "default": "./_cjs/actions/index.js" }, + "./actions/erc7579": { + "types": "./_types/actions/index.d.ts", + "import": "./_esm/actions/index.js", + "default": "./_cjs/actions/index.js" + }, "./actions/pimlico": { "types": "./_types/actions/pimlico.d.ts", "import": "./_esm/actions/pimlico.js", @@ -81,6 +86,6 @@ } }, "peerDependencies": { - "viem": "^2.9.17" + "viem": "^2.14.1" } } diff --git a/packages/permissionless/types/index.ts b/packages/permissionless/types/index.ts index 06a01060..486a26c1 100644 --- a/packages/permissionless/types/index.ts +++ b/packages/permissionless/types/index.ts @@ -1,5 +1,4 @@ import type { Account, Chain, Client, Transport } from "viem" -import type { IsUndefined } from "viem/types/utils" import type { SmartAccount } from "../accounts/types" import type { EntryPoint } from "./entrypoint" import type { UserOperation } from "./userOperation" @@ -14,6 +13,8 @@ export type { export type { PackedUserOperation } from "./userOperation" +export type IsUndefined = [undefined] extends [T] ? true : false + export type GetAccountParameterWithClient< TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined, @@ -24,9 +25,7 @@ export type GetAccountParameterWithClient< export type GetAccountParameter< entryPoint extends EntryPoint, - TAccount extends SmartAccount | undefined = - | SmartAccount - | undefined + TAccount extends SmartAccount | undefined > = IsUndefined extends true ? { account: SmartAccount } : { account?: SmartAccount } diff --git a/packages/permissionless/utils/encode7579CallData.ts b/packages/permissionless/utils/encode7579CallData.ts new file mode 100644 index 00000000..2b67887f --- /dev/null +++ b/packages/permissionless/utils/encode7579CallData.ts @@ -0,0 +1,114 @@ +import { + type Address, + type Hex, + concatHex, + encodeAbiParameters, + encodeFunctionData, + toHex +} from "viem" +import { + type CallType, + type ExecutionMode, + encodeExecutionMode +} from "../actions/erc7579/supportsExecutionMode" + +export type EncodeCallDataParams = { + mode: ExecutionMode + callData: callType extends "batchcall" + ? { + to: Address + value: bigint + data: Hex + }[] + : { + to: Address + value: bigint + data: Hex + } +} + +export function encode7579CallData({ + mode, + callData +}: EncodeCallDataParams): Hex { + if (Array.isArray(callData) && mode?.type !== "batchcall") { + throw new Error( + `mode ${mode} does not supported for batchcall calldata` + ) + } + + const executeAbi = [ + { + type: "function", + name: "execute", + inputs: [ + { + name: "execMode", + type: "bytes32", + internalType: "ExecMode" + }, + { + name: "executionCalldata", + type: "bytes", + internalType: "bytes" + } + ], + outputs: [], + stateMutability: "payable" + } + ] as const + + if (Array.isArray(callData)) { + return encodeFunctionData({ + abi: executeAbi, + functionName: "execute", + args: [ + encodeExecutionMode(mode), + encodeAbiParameters( + [ + { + name: "executionBatch", + type: "tuple[]", + components: [ + { + name: "target", + type: "address" + }, + { + name: "value", + type: "uint256" + }, + { + name: "callData", + type: "bytes" + } + ] + } + ], + [ + callData.map((arg) => { + return { + target: arg.to, + value: arg.value, + callData: arg.data + } + }) + ] + ) + ] + }) + } + + return encodeFunctionData({ + abi: executeAbi, + functionName: "execute", + args: [ + encodeExecutionMode(mode), + concatHex([ + callData.to, + toHex(callData.value, { size: 32 }), + callData.data + ]) + ] + }) +} diff --git a/packages/permissionless/vitest.config.ts b/packages/permissionless/vitest.config.ts index 0361eae6..3a077b01 100644 --- a/packages/permissionless/vitest.config.ts +++ b/packages/permissionless/vitest.config.ts @@ -3,9 +3,6 @@ import { defineConfig } from "vitest/config" export default defineConfig({ test: { - alias: { - permissionless: join(__dirname, "./") - }, coverage: { all: true, provider: "v8", diff --git a/packages/wagmi-test-demo/src/App.tsx b/packages/wagmi-test-demo/src/App.tsx index 10dd17f9..fa5401bb 100644 --- a/packages/wagmi-test-demo/src/App.tsx +++ b/packages/wagmi-test-demo/src/App.tsx @@ -111,8 +111,6 @@ function App() { }) } - console.log("error: ", sendTransactionError) - return ( <>