Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions .pnpmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Hoist ts-node and other CLI tools to avoid binary linking issues
hoist-pattern[]=*ts-node*
hoist-pattern[]=*hardhat*

# Enable strict peer dependencies
strict-peer-dependencies=false
4 changes: 2 additions & 2 deletions alto-local.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"entrypoints": "0x0000000071727De22E5E9d8BAf0edAc6f37da032",
"entrypoints": "0x0000000071727De22E5E9d8BAf0edAc6f37da032,0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
"_executor-private-keys": "0x211899abe67f2ef5fc79849d05fd075a4c0150d0ff517946a0a1c257136153fa",
"executor-private-keys": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
"utility-private-key": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
"rpc-url": "http://localhost:8545",
"rpc-url": "http://127.0.0.1:8545",
"rpc-log-level": "trace",
"safe-mode": false
}
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
"build:connector": "pnpm -F @appliedblockchain/giano-connector build",
"git:init": "git submodule update --init --recursive",
"bundler:start": "alto --config ./alto-local.json",
"bundler:cors": "lcp --proxyUrl http://localhost:3000 --port 4337",
"bundler:cors": "lcp --proxyUrl http://127.0.0.1:3000 --port 4337",
"bundler:dev": "npm-run-all -p --race bundler:start bundler:cors",
"aa:deploy:local": "cd vendor/account-abstraction && env COREPACK_ENABLE_STRICT=0 corepack yarn@1 && env COREPACK_ENABLE_STRICT=0 corepack yarn@1 deploy --network localhost",
"aa:deploy:local": "npm run aa:deploy:local:v07 && npm run aa:deploy:local:v08",
"aa:deploy:local:v07": "cd vendor/account-abstraction && git checkout v0.7.0 && env COREPACK_ENABLE_STRICT=0 corepack yarn@1 && env COREPACK_ENABLE_STRICT=0 corepack yarn@1 deploy --network localhost",
"aa:deploy:local:v08": "cd vendor/account-abstraction && git checkout v0.8.0 && env COREPACK_ENABLE_STRICT=0 corepack yarn@1 && env COREPACK_ENABLE_STRICT=0 corepack yarn@1 deploy --network localhost",
"hh:initlocal": "pnpm --filter @appliedblockchain/giano-contracts hh:initlocal",
"hh:node": "pnpm --filter @appliedblockchain/giano-contracts hh:node",
"hh:deploy": "pnpm --filter @appliedblockchain/giano-contracts hh:deploy",
Expand Down
32 changes: 25 additions & 7 deletions packages/connector/src/account/toGianoSmartAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,41 @@ import {
toHex,
} from 'viem';
import type { SmartAccount, SmartAccountImplementation, UserOperation, WebAuthnAccount } from 'viem/account-abstraction';
import { entryPoint07Abi } from 'viem/account-abstraction';
import { entryPoint07Address, getUserOperationHash, toSmartAccount } from 'viem/account-abstraction';
import { entryPoint07Abi, entryPoint08Abi } from 'viem/account-abstraction';
import { entryPoint07Address, entryPoint08Address, getUserOperationHash, toSmartAccount } from 'viem/account-abstraction';
import { readContract } from 'viem/actions';
import type { EntryPointConfig } from '../giano-entry-point';

export type ToGianoSmartAccountParameters = {
address?: Address | undefined;
client: GianoSmartAccountImplementation['client'];
owners: readonly (Address | OneOf<LocalAccount | WebAuthnAccount>)[];
nonce?: bigint | undefined;
factoryAddress: Address;
entryPoint?: EntryPointConfig;
};

export type GianoSmartAccountImplementation = GianoSmartAccountImplementationV07 | GianoSmartAccountImplementationV08;

export type ToGianoSmartAccountReturnType = Prettify<SmartAccount<GianoSmartAccountImplementation>>;

export type GianoSmartAccountImplementation = Assign<
export type GianoSmartAccountImplementationV07 = Assign<
SmartAccountImplementation<typeof entryPoint07Abi, '0.7', { abi: typeof abi; factory: { abi: typeof factoryAbi; address: Address } }>,
{
decodeCalls: NonNullable<SmartAccountImplementation['decodeCalls']>;
sign: NonNullable<SmartAccountImplementation['sign']>;
signStaticCallPermission(): Promise<{ signature: Hex; signedAt: number }>;
}
>;
>;

export type GianoSmartAccountImplementationV08 = Assign<
SmartAccountImplementation<typeof entryPoint08Abi, '0.8', { abi: typeof abi; factory: { abi: typeof factoryAbi; address: Address } }>,
{
decodeCalls: NonNullable<SmartAccountImplementation['decodeCalls']>;
sign: NonNullable<SmartAccountImplementation['sign']>;
signStaticCallPermission(): Promise<{ signature: Hex; signedAt: number }>;
}
>;

/**
* @description Create a Giano Smart Account.
Expand All @@ -61,11 +74,16 @@ export type GianoSmartAccountImplementation = Assign<
* })
*/
export async function toGianoSmartAccount(parameters: ToGianoSmartAccountParameters): Promise<ToGianoSmartAccountReturnType> {
const { client, owners, nonce = 0n, factoryAddress } = parameters;
const { client, owners, nonce = 0n, factoryAddress, entryPoint: entryPointConfig } = parameters;

let address = parameters.address;

const entryPoint = {
// Use provided EntryPoint configuration or default to v0.7
const entryPoint = entryPointConfig ? {
abi: entryPointConfig.version === '0.8' ? entryPoint08Abi : entryPoint07Abi,
address: entryPointConfig.address,
version: entryPointConfig.version,
} as const : {
abi: entryPoint07Abi,
address: entryPoint07Address,
version: '0.7',
Expand Down Expand Up @@ -265,7 +283,7 @@ export async function toGianoSmartAccount(parameters: ToGianoSmartAccountParamet
},

extend: { abi, factory, signStaticCallPermission },
});
}) as unknown as ToGianoSmartAccountReturnType;
}

/////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
53 changes: 51 additions & 2 deletions packages/connector/src/giano-entry-point.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,56 @@
import { entryPoint07Address, EntryPointVersion } from 'viem/account-abstraction'
import { entryPoint07Address, entryPoint08Address, EntryPointVersion } from 'viem/account-abstraction'

// EntryPoint v0.8 address - PRODUCTION CONFIGURATION
export const ENTRYPOINT_V08_ADDRESS = entryPoint08Address

export type SupportedEntryPointVersion = '0.7' | '0.8'

export interface EntryPointConfig {
version: SupportedEntryPointVersion
address: `0x${string}`
}

// Default configuration for EntryPoint v0.7
export const ENTRYPOINT_V07_CONFIG: EntryPointConfig = {
version: '0.7',
address: entryPoint07Address
}

// Configuration for EntryPoint v0.8
export const ENTRYPOINT_V08_CONFIG: EntryPointConfig = {
version: '0.8',
address: ENTRYPOINT_V08_ADDRESS
}

// Available EntryPoint configurations
export const ENTRYPOINT_CONFIGS = {
'0.7': ENTRYPOINT_V07_CONFIG,
'0.8': ENTRYPOINT_V08_CONFIG
} as const

// Default EntryPoint version (maintaining backward compatibility)
export const DEFAULT_ENTRYPOINT_VERSION: SupportedEntryPointVersion = '0.7'

// Legacy exports for backward compatibility
export const GianoEntryPointVersion = '0.7' satisfies EntryPointVersion
export type GianoEntryPointVersion = typeof GianoEntryPointVersion

export const GianoEntryPointAddress = entryPoint07Address
export type GianoEntryPointAddress = typeof GianoEntryPointAddress

// New exports for version-aware EntryPoint support
export function getEntryPointConfig(version: SupportedEntryPointVersion): EntryPointConfig {
return ENTRYPOINT_CONFIGS[version]
}

export function getEntryPointAddress(version: SupportedEntryPointVersion): `0x${string}` {
return ENTRYPOINT_CONFIGS[version].address
}

export function getEntryPointVersion(address: `0x${string}`): SupportedEntryPointVersion | null {
for (const [version, config] of Object.entries(ENTRYPOINT_CONFIGS)) {
if (config.address.toLowerCase() === address.toLowerCase()) {
return version as SupportedEntryPointVersion
}
}
return null
}
38 changes: 30 additions & 8 deletions packages/connector/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ import { createWebAuthnCredential, toWebAuthnAccount } from 'viem/account-abstra
import type { EIP1193EventMap, EIP1193Parameters, EIP1193RequestFn } from 'viem/types/eip1193';
import type { GianoSmartAccountImplementation } from './account';
import { toGianoSmartAccount } from './account';
import { GianoEntryPointAddress, GianoEntryPointVersion } from './giano-entry-point'
import {
GianoEntryPointAddress,
GianoEntryPointVersion,
SupportedEntryPointVersion,
getEntryPointConfig,
DEFAULT_ENTRYPOINT_VERSION
} from './giano-entry-point'
import { GianoProviderInjection } from './provider-injection'
import { withValidation } from './provider-injection/_with-validation'
import { v4 as uuidv4 } from 'uuid';
Expand Down Expand Up @@ -63,6 +69,7 @@ export type CreateGianoProviderParams = {
gianoSmartWalletFactoryAddress: Address;
userVerification?: 'required' | 'preferred' | 'discouraged';
mediation?: 'silent' | 'optional' | 'required';
entryPointVersion?: SupportedEntryPointVersion;
};

type EventHandler<E extends keyof EIP1193EventMap> = (payload: Parameters<EIP1193EventMap[E]>[0]) => void;
Expand All @@ -79,6 +86,7 @@ type GianoProviderCustomMethods = [{
export type GianoProvider = EIP1193Provider & {
request: EIP1193RequestFn<GianoProviderCustomMethods>
getSmartAccount: () => SmartAccount<GianoSmartAccountImplementation> | null;
getCurrentEntryPoint: () => `0x${string}`;
}

export const createGianoProvider = (options: CreateGianoProviderParams) => {
Expand All @@ -90,9 +98,13 @@ export const createGianoProvider = (options: CreateGianoProviderParams) => {
bundler,
gianoSmartWalletFactoryAddress,
userVerification = USER_VERIFICATION_REQUIREMENT,
mediation = 'silent'
mediation = 'silent',
entryPointVersion = DEFAULT_ENTRYPOINT_VERSION
} = options

// Get the EntryPoint configuration for the specified version
const entryPointConfig = getEntryPointConfig(entryPointVersion)

let smartAccount: SmartAccount<GianoSmartAccountImplementation> | null;
let chain: Chain | undefined;
let transport: Transport | undefined;
Expand Down Expand Up @@ -133,16 +145,18 @@ export const createGianoProvider = (options: CreateGianoProviderParams) => {
// Sign the user operation
const signature = await userOpRequest.account.signUserOperation(preparedWithGas);

console.log(entryPointConfig)

// Create the complete signed user operation
const signedUserOp = {
...preparedWithGas,
sender: await userOpRequest.account.getAddress(),
signature,
account: {
entryPoint: {
address: GianoEntryPointAddress,
signature,
account: {
entryPoint: {
address: entryPointConfig.address,
},
},
},
};

return await injection.submitUserOperation(signedUserOp);
Expand Down Expand Up @@ -307,7 +321,12 @@ export const createGianoProvider = (options: CreateGianoProviderParams) => {
if (!webAuthnAccount) {
throw new Error('Invalid credential');
}
smartAccount = await toGianoSmartAccount({ client: client!, owners: [webAuthnAccount], factoryAddress: gianoSmartWalletFactoryAddress })
smartAccount = await toGianoSmartAccount({
client: client!,
owners: [webAuthnAccount],
factoryAddress: gianoSmartWalletFactoryAddress,
entryPoint: entryPointConfig
})
const smartAccountAddress = await smartAccount.getAddress()

emit('connect', { chainId: `0x${chain!.id.toString(16)}` });
Expand Down Expand Up @@ -340,6 +359,7 @@ export const createGianoProvider = (options: CreateGianoProviderParams) => {
owners: [toWebAuthnAccount({ credential })],
address: handlerCreatedAddress,
factoryAddress: gianoSmartWalletFactoryAddress,
entryPoint: entryPointConfig,
});

emit('connect', { chainId });
Expand All @@ -351,6 +371,7 @@ export const createGianoProvider = (options: CreateGianoProviderParams) => {
client: client!,
owners: [toWebAuthnAccount({ credential })],
factoryAddress: gianoSmartWalletFactoryAddress,
entryPoint: entryPointConfig,
});
const smartAccountAddress = await smartAccount.getAddress();

Expand Down Expand Up @@ -510,6 +531,7 @@ export const createGianoProvider = (options: CreateGianoProviderParams) => {

const provider: GianoProvider = {
getSmartAccount: () => smartAccount,
getCurrentEntryPoint: () => entryPointConfig.address,
request: async (args: EIP1193Parameters) => {
const { method, params } = args;

Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const config: HardhatUserConfig = {
},
localhost: {
enableRip7212: true,
url: 'http://localhost:8545',
url: 'http://127.0.0.1:8545',
},
['base-sepolia']: {
enableRip7212: true,
Expand Down
22 changes: 19 additions & 3 deletions packages/contracts/ignition/modules/GianoAccountFactory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import { buildModule } from '@nomicfoundation/hardhat-ignition/modules';

export default buildModule('GianoAccountFactory', (m) => {
const gianoAccountImplementation = m.contract('GianoSmartWallet');
const gianoAccountFactory = m.contract('GianoSmartWalletFactory', [gianoAccountImplementation]);
// Deploy V07 implementation (initial deployment target)
const gianoAccountImplementationV07 = m.contract('GianoSmartWallet');

// Deploy V08 implementation (upgrade target)
const gianoAccountImplementationV08 = m.contract('GianoSmartWalletV08Implementation');

// Deploy factory using V07 implementation (users start with V07)
const gianoAccountFactory = m.contract('GianoSmartWalletFactory', [gianoAccountImplementationV07]);

return { gianoAccountFactory };
return {
// Primary deployments
gianoAccountFactory,
gianoAccountImplementationV07,
gianoAccountImplementationV08,

// For convenience in upgrade scripts
v07Implementation: gianoAccountImplementationV07,
v08Implementation: gianoAccountImplementationV08,
factory: gianoAccountFactory
};
});
8 changes: 5 additions & 3 deletions packages/contracts/ignition/modules/Testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { parseEther } from 'ethers';

export default buildModule('Testing', (m) => {
const privateERC20 = m.contract('PrivateERC20', [parseEther('100000000000000')]);
const permissivePaymaster = m.contract('PermissivePaymaster', ['0x0000000071727De22E5E9d8BAf0edAc6f37da032']);
const permissivePaymasterv07 = m.contract('src/testing/PermissivePaymaster.sol:PermissivePaymaster', ['0x0000000071727De22E5E9d8BAf0edAc6f37da032'], { id: 'PermissivePaymasterV07' });
const permissivePaymasterv08 = m.contract('PermissivePaymasterV08', ['0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108'], { id: 'PermissivePaymasterV08' });

m.send('fundPaymaster', permissivePaymaster, parseEther('500'));
m.send('fundPaymasterV07', permissivePaymasterv07, parseEther('500'));
m.send('fundPaymasterV08', permissivePaymasterv08, parseEther('500'));

return { privateERC20, permissivePaymaster };
return { privateERC20, permissivePaymasterv07, permissivePaymasterv08 };
});
5 changes: 3 additions & 2 deletions packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "pnpm hh:compile && pnpm hh:wagmi && tsup index.ts",
"hh:test": "NODE_ENV=test REPORT_GAS=true hardhat test",
"hh:node": "anvil --enable-trace-printing",
"hh:node": "anvil --steps-tracing",
"hh:deploy": "hardhat ignition deploy ignition/modules/GianoAccountFactory.ts --strategy create2",
"hh:deploy:mapper": "hardhat ignition deploy ignition/modules/index.ts --strategy create2",
"hh:deploy:testing": "hardhat ignition deploy ignition/modules/Testing.ts --strategy create2",
Expand All @@ -23,7 +23,8 @@
"main": "dist/index",
"types": "dist/index.d.ts",
"devDependencies": {
"@account-abstraction/contracts": "0.7.0",
"account-abstraction-v07": "npm:@account-abstraction/[email protected]",
"account-abstraction-v08": "npm:@account-abstraction/contracts@^0.8.0",
"@appliedblockchain/silentdatarollup-core": "^1.0.1",
"@appliedblockchain/silentdatarollup-hardhat-plugin": "^1.0.1",
"@nomicfoundation/ethereumjs-util": "^9.0.4",
Expand Down
Loading