Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8476236
feat: permissions WIP
Zer0dot Mar 27, 2025
4ce730e
feat: (WIP) working on permissions
Zer0dot Mar 27, 2025
c846547
feat: (WIP) permission work
Zer0dot Mar 28, 2025
d7c44d9
feat: (WIP) permission builder
Zer0dot Apr 1, 2025
86570a4
feat: update permission builder to take in key
howydev Apr 1, 2025
07fe4af
feat: (wip) permission builder
Zer0dot Apr 2, 2025
dc2dda3
feat: (WIP) add sensible defaults to permission builder
Zer0dot Apr 2, 2025
6ffb43c
fix: fix missing add permission on root
Zer0dot Apr 3, 2025
18e8466
test: (wip) updating tests with permission builder
Zer0dot Apr 3, 2025
8c73fe4
test: remove obsolete test
Zer0dot Apr 3, 2025
d242224
fix: boom lfg
howydev Apr 3, 2025
6d1d65c
chore: lint
howydev Apr 3, 2025
4509ea9
fix: test
howydev Apr 3, 2025
bd94d6f
test: deferred actions e2e (#1505)
howydev Apr 4, 2025
f3dea95
chore: add new errors (#1509)
howydev Apr 4, 2025
378c938
fix: (wip) small fix, adapt test
Zer0dot Apr 4, 2025
e9ee680
fix: (wip) minor fix and update
Zer0dot Apr 4, 2025
7b27d2a
feat: adapt permission builder to new structure
Zer0dot Apr 5, 2025
0a2e072
chore: update
howydev Apr 7, 2025
cf46a00
chore: remove unused action
howydev Apr 7, 2025
4446703
chore: more fixes
howydev Apr 7, 2025
23fbf6e
chore: update viem peer dep
Zer0dot Apr 7, 2025
63e440a
Revert "chore: update viem peer dep"
Zer0dot Apr 7, 2025
9e0c6dd
Update aa-sdk/core/src/errors/client.ts
Zer0dot Apr 7, 2025
7787ee8
Update aa-sdk/core/src/errors/client.ts
Zer0dot Apr 7, 2025
cb255ff
Update account-kit/smart-contracts/src/ma-v2/permissionBuilder.ts
Zer0dot Apr 7, 2025
5e8eee5
Update account-kit/smart-contracts/src/ma-v2/permissionBuilder.ts
Zer0dot Apr 7, 2025
849e186
Update account-kit/smart-contracts/src/ma-v2/permissionBuilder.ts
Zer0dot Apr 7, 2025
9e9ed1c
chore: remove docs that don't seem to belong to changes in this branch
howydev Apr 7, 2025
d629ea1
fix: test fail
howydev Apr 7, 2025
b2cc4a5
fix: more test failures
howydev Apr 7, 2025
baaebf6
chore: add additions to exports
howydev Apr 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions aa-sdk/core/src/errors/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,31 @@ export class InvalidModularAccountV2Mode extends BaseError {
super(`The provided account mode is invalid for ModularAccount V2`);
}
}

/**
* Error class denoting that the deferred action mode used is invalid.
*/
export class InvalidDeferredActionMode extends BaseError {
override name = "InvalidDeferredActionMode";

/**
* Initializes a new instance of the error message with a default message indicating that the provided deferred action mode is invalid.
*/
constructor() {
super(`The provided deferred action mode is invalid`);
}
}

/**
* Error class denoting that the deferred action nonce used is invalid.
*/
export class InvalidDeferredActionNonce extends BaseError {
override name = "InvalidDeferredActionNonce";

/**
* Initializes a new instance of the error message with a default message indicating that the provided deferred action nonce is invalid.
*/
constructor() {
super(`The provided deferred action nonce is invalid`);
}
}
2 changes: 2 additions & 0 deletions aa-sdk/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export {
InvalidNonceKeyError,
EntityIdOverrideError,
InvalidModularAccountV2Mode,
InvalidDeferredActionMode,
InvalidDeferredActionNonce,
} from "./errors/client.js";
export {
EntryPointNotFoundError,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
getEntryPoint,
InvalidEntityIdError,
InvalidNonceKeyError,
InvalidDeferredActionNonce,
InvalidDeferredActionMode,
toSmartContractAccount,
type AccountOp,
type SmartAccountSigner,
Expand Down Expand Up @@ -85,6 +87,7 @@ export type CreateMAV2BaseParams<
signer: TSigner;
signerEntity?: SignerEntity;
accountAddress: Address;
deferredAction?: Hex;
};

export type CreateMAV2BaseReturnType<
Expand All @@ -108,6 +111,7 @@ export async function createMAv2Base<
entityId = DEFAULT_OWNER_ENTITY_ID,
} = {},
accountAddress,
deferredAction,
...remainingToSmartContractAccountParams
} = config;

Expand All @@ -120,6 +124,39 @@ export async function createMAv2Base<
chain,
});

const entryPointContract = getContract({
address: entryPoint.address,
abi: entryPoint.abi,
client,
});

let useDeferredAction: boolean = false;
let nonce: bigint = 0n;
let deferredActionData: Hex = "0x";
let hasAssociatedExecHooks: boolean = false;

if (deferredAction) {
if (deferredAction.slice(2, 4) !== "00") {
throw new InvalidDeferredActionMode();
}
// Set these values if the deferred action has not been consumed. We check this with the EP
const nextNonceForDeferredAction: bigint =
(await entryPointContract.read.getNonce([
accountAddress,
nonce >> 64n,
])) as bigint;

// we only add the deferred action in if the nonce has not been consumed
if (nonce === nextNonceForDeferredAction) {
nonce = BigInt(`0x${deferredAction.slice(6, 70)}`);
useDeferredAction = true;
deferredActionData = `0x${deferredAction.slice(70)}`;
hasAssociatedExecHooks = deferredAction[5] === "1";
} else if (nonce > nextNonceForDeferredAction) {
throw new InvalidDeferredActionNonce();
}
}

const encodeExecute: (tx: AccountOp) => Promise<Hex> = async ({
target,
data,
Expand Down Expand Up @@ -150,18 +187,16 @@ export async function createMAv2Base<

const isAccountDeployed: () => Promise<boolean> = async () =>
!!(await client.getCode({ address: accountAddress }));
// TODO: add deferred action flag

const getNonce = async (nonceKey: bigint = 0n): Promise<bigint> => {
if (useDeferredAction) {
return nonce;
}

if (nonceKey > maxUint152) {
throw new InvalidNonceKeyError(nonceKey);
}

const entryPointContract = getContract({
address: entryPoint.address,
abi: entryPoint.abi,
client,
});

const fullNonceKey: bigint =
(nonceKey << 40n) +
(BigInt(entityId) << 8n) +
Expand Down Expand Up @@ -216,7 +251,8 @@ export async function createMAv2Base<
entityId: Number(entityId),
});

return validationData.executionHooks.length
return (useDeferredAction && hasAssociatedExecHooks) ||
validationData.executionHooks.length
? concatHex([executeUserOpSelector, callData])
: callData;
};
Expand All @@ -231,8 +267,14 @@ export async function createMAv2Base<
encodeBatchExecute,
getNonce,
...(entityId === DEFAULT_OWNER_ENTITY_ID
? nativeSMASigner(signer, chain, accountAddress)
: singleSignerMessageSigner(signer, chain, accountAddress, entityId)),
? nativeSMASigner(signer, chain, accountAddress, deferredActionData)
: singleSignerMessageSigner(
signer,
chain,
accountAddress,
entityId,
deferredActionData
)),
});

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type CreateModularAccountV2Params<
> & {
signer: TSigner;
entryPoint?: EntryPointDef<"0.7.0", Chain>;
deferredAction?: Hex;
signerEntity?: SignerEntity;
}) &
(
Expand Down Expand Up @@ -103,6 +104,7 @@ export async function createModularAccountV2(
entityId: DEFAULT_OWNER_ENTITY_ID,
},
signerEntity: { entityId = DEFAULT_OWNER_ENTITY_ID } = {},
deferredAction,
} = config;

const client = createBundlerClient({
Expand Down Expand Up @@ -183,6 +185,7 @@ export async function createModularAccountV2(
signer,
entryPoint,
signerEntity,
deferredAction,
...accountFunctions,
});
}
Expand Down
34 changes: 20 additions & 14 deletions account-kit/smart-contracts/src/ma-v2/account/nativeSMASigner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
type Chain,
type Address,
concat,
concatHex,
} from "viem";

import {
Expand All @@ -23,7 +24,6 @@ import { SignatureType } from "../modules/utils.js";
* @example
* ```ts
* import { nativeSMASigner } from "@account-kit/smart-contracts";

* import { LocalAccountSigner } from "@aa-sdk/core";
*
* const MNEMONIC = "...":
Expand All @@ -38,31 +38,37 @@ import { SignatureType } from "../modules/utils.js";
* @param {SmartAccountSigner} signer Signer to use for signing operations
* @param {Chain} chain Chain object for the signer
* @param {Address} accountAddress address of the smart account using this signer
* @param {Hex} deferredActionData optional deferred action data to prepend to the uo signatures
* @returns {object} an object with methods for signing operations and managing signatures
*/
export const nativeSMASigner = (
signer: SmartAccountSigner,
chain: Chain,
accountAddress: Address
accountAddress: Address,
deferredActionData?: Hex
) => {
return {
getDummySignature: (): Hex => {
const dummyEcdsaSignature =
"0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c";

return packUOSignature({
const sig = packUOSignature({
// orderedHookData: [],
validationSignature: dummyEcdsaSignature,
validationSignature:
"0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c",
});

return deferredActionData ? concatHex([deferredActionData, sig]) : sig;
},

signUserOperationHash: (uoHash: Hex): Promise<Hex> => {
return signer.signMessage({ raw: uoHash }).then((signature: Hex) =>
packUOSignature({
// orderedHookData: [],
validationSignature: signature,
})
);
signUserOperationHash: async (uoHash: Hex): Promise<Hex> => {
const sig = await signer
.signMessage({ raw: uoHash })
.then((signature: Hex) =>
packUOSignature({
// orderedHookData: [],
validationSignature: signature,
})
);

return deferredActionData ? concatHex([deferredActionData, sig]) : sig;
},

// we apply the expected 1271 packing here since the account contract will expect it
Expand Down
Loading
Loading