From 4a19ca3422783bade5afa8b0b404684f626fce21 Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Tue, 6 Jun 2023 23:26:51 +0500 Subject: [PATCH 1/9] versioning enabled --- packages/account/src/BaseAccount.ts | 15 ++- packages/account/src/BiconomySmartAccount.ts | 117 +++++++++++++----- .../src/interfaces/IBiconomySmartAccount.ts | 4 + packages/account/src/utils/Constants.ts | 20 +-- packages/account/src/utils/Types.ts | 12 ++ packages/bundler/src/Bundler.ts | 4 +- packages/common/src/ContractsInstances.ts | 61 +++++++++ packages/common/src/index.ts | 1 + packages/core-types/src/SmartAccountTypes.ts | 6 + 9 files changed, 199 insertions(+), 41 deletions(-) create mode 100644 packages/common/src/ContractsInstances.ts diff --git a/packages/account/src/BaseAccount.ts b/packages/account/src/BaseAccount.ts index 8248550b0..58f7ba28a 100644 --- a/packages/account/src/BaseAccount.ts +++ b/packages/account/src/BaseAccount.ts @@ -8,7 +8,7 @@ import { packUserOp } from '@biconomy/common' import { IBundler, UserOpResponse } from '@biconomy/bundler' import { IPaymaster } from '@biconomy/paymaster' -import { EntryPoint_v100, SmartAccount_v100 } from '@biconomy/common' +import { EntryPoint_v100, SmartAccount_v100, Logger } from '@biconomy/common' import { SmartAccountConfig, Overrides } from './utils/Types' type UserOperationKey = keyof UserOperation @@ -18,12 +18,21 @@ export abstract class SmartAccount implements ISmartAccount { paymaster!: IPaymaster initCode: string = '0x' proxy!: SmartAccount_v100 + owner!: string provider!: JsonRpcProvider entryPoint!: EntryPoint_v100 chainId!: ChainId signer!: Signer + smartAccountConfig: SmartAccountConfig - constructor(readonly smartAccountConfig: SmartAccountConfig) { } + constructor(_smartAccountConfig: SmartAccountConfig) { + this.smartAccountConfig = _smartAccountConfig + } + + + setEntrypointAddress(entryPointAddress: string){ + this.smartAccountConfig.entryPointAddress = entryPointAddress + } private validateUserOp(userOp: Partial, requiredFields: UserOperationKey[]): boolean { for (let field of requiredFields) { @@ -66,7 +75,7 @@ export abstract class SmartAccount implements ISmartAccount { userOp = { ...userOp, ...overrides } } - console.log('userOp in estimation', userOp); + Logger.log('userOp in estimation', userOp); // Defining the keys that are related that can be overrides const overrideGasFields: UserOperationKey[] = [ diff --git a/packages/account/src/BiconomySmartAccount.ts b/packages/account/src/BiconomySmartAccount.ts index 4b91975f9..a32e3c4b2 100644 --- a/packages/account/src/BiconomySmartAccount.ts +++ b/packages/account/src/BiconomySmartAccount.ts @@ -1,20 +1,22 @@ import { JsonRpcProvider } from '@ethersproject/providers' -import {ethers, BigNumberish, BytesLike, BigNumber } from 'ethers' +import { ethers, BigNumberish, BytesLike, BigNumber } from 'ethers' import { SmartAccount } from './BaseAccount' import { + Logger, NODE_CLIENT_URL, RPC_PROVIDER_URLS, - EntryPoint_v100__factory, SmartAccountFactory_v100, - SmartAccountFactory_v100__factory, - SmartAccount_v100__factory + getEntryPointContractInstance, + getFactoryContractInstance, + getProxyContractInstance } from '@biconomy/common' import { BiconomySmartAccountConfig, Overrides } from './utils/Types' -import { UserOperation, Transaction } from '@biconomy/core-types' +import { UserOperation, Transaction, SmartAccountType } from '@biconomy/core-types' import NodeClient from '@biconomy/node-client' import INodeClient from '@biconomy/node-client' import { IBiconomySmartAccount } from 'interfaces/IBiconomySmartAccount' import { + ISmartAccount, SupportedChainsResponse, BalancesResponse, BalancesDto, @@ -23,13 +25,15 @@ import { SmartAccountsResponse, SCWTransactionResponse } from '@biconomy/node-client' -import { ENTRYPOINT_ADDRESSES, BICONOMY_FACTORY_ADDRESSES } from './utils/Constants' +import { ENTRYPOINT_ADDRESSES, BICONOMY_FACTORY_ADDRESSES, BICONOMY_IMPLEMENTATION_ADDRESSES } from './utils/Constants' export class BiconomySmartAccount extends SmartAccount implements IBiconomySmartAccount { - private factory: SmartAccountFactory_v100 + private factory!: SmartAccountFactory_v100 private nodeClient: INodeClient - private accountIndex!: Number + private accountIndex!: number private address!: string + private smartAccountInfo!: ISmartAccount + private isInited!: boolean constructor(readonly biconomySmartAccountConfig: BiconomySmartAccountConfig) { const { @@ -44,27 +48,24 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart } = biconomySmartAccountConfig const _entryPointAddress = entryPointAddress ?? ENTRYPOINT_ADDRESSES.default - const _factoryAddress = factoryAddress ?? BICONOMY_FACTORY_ADDRESSES.default super({ bundler, entryPointAddress: _entryPointAddress }) const _rpcUrl = rpcUrl ?? RPC_PROVIDER_URLS[chainId] - - if (!_rpcUrl){ + + if (!_rpcUrl) { throw new Error(`Chain Id ${chainId} is not supported. Please refer to the following link for supported chains list https://docs.biconomy.io/build-with-biconomy-sdk/gasless-transactions#supported-chains`) } this.provider = new JsonRpcProvider(_rpcUrl) - this.entryPoint = EntryPoint_v100__factory.connect(_entryPointAddress, this.provider) - this.factory = SmartAccountFactory_v100__factory.connect(_factoryAddress, this.provider) this.nodeClient = new NodeClient({ txServiceUrl: nodeClientUrl ?? NODE_CLIENT_URL }) this.signer = signer if (paymaster) { this.paymaster = paymaster } - if ( bundler ) - this.bundler = bundler + if (bundler) + this.bundler = bundler } /** * @description This function will initialise BiconomyAccount class state @@ -74,38 +75,90 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart try { this.isProviderDefined() this.isSignerDefined() - await this.setAccountIndex(accountIndex) + this.owner = await this.signer.getAddress() this.chainId = await this.provider.getNetwork().then((net) => net.chainId) + await this.setAccountIndex(accountIndex) + this.isInited = true } catch (error) { - console.error(`Failed to call init: ${error}`); + Logger.error(`Failed to call init: ${error}`); throw error } return this } + private isInitialized(): boolean{ + if (!this.isInited) + throw new Error('BiconomySmartAccount is not initialized. Please call BiconomySmartAccount.init() before interacting with any other function') + return true + } + + private setProxyContractState(){ + const proxyInstanceDto = { + smartAccountType: SmartAccountType.BICONOMY, + version: BICONOMY_IMPLEMENTATION_ADDRESSES[this.address], + contractAddress: this.address, + provider: this.provider + } + this.proxy = getProxyContractInstance(proxyInstanceDto) + } + + private setEntryPointContractState(){ + const _entryPointAddress = this.smartAccountInfo.entryPointAddress + this.setEntrypointAddress(_entryPointAddress) + const entryPointInstanceDto = { + smartAccountType: SmartAccountType.BICONOMY, + version: ENTRYPOINT_ADDRESSES[_entryPointAddress], + contractAddress: _entryPointAddress, + provider: this.provider + } + this.entryPoint = getEntryPointContractInstance(entryPointInstanceDto) + } + + private setFactoryContractState(){ + const _factoryAddress = this.smartAccountInfo.factoryAddress + const factoryInstanceDto = { + smartAccountType: SmartAccountType.BICONOMY, + version: BICONOMY_FACTORY_ADDRESSES[_factoryAddress], + contractAddress: _factoryAddress, + provider: this.provider + } + this.factory = getFactoryContractInstance(factoryInstanceDto) + } + + private async setContractsState() { + this.setProxyContractState() + this.setEntryPointContractState() + this.setFactoryContractState() + } + async setAccountIndex(accountIndex: number): Promise { + this.isInitialized() this.accountIndex = accountIndex this.address = await this.getSmartAccountAddress(accountIndex) - this.proxy = await SmartAccount_v100__factory.connect(this.address, this.provider) + await this.setContractsState() + await this.setInitCode(this.accountIndex) } async getSmartAccountAddress(accountIndex: number = 0): Promise { try { this.isSignerDefined() - this.getInitCode(accountIndex) - const address = await this.factory.getAddressForCounterFactualAccount( - await this.signer.getAddress(), - ethers.BigNumber.from(accountIndex) - ) - return address + let smartAccountsList: ISmartAccount[] = (await this.getSmartAccountsByOwner({ + chainId: this.chainId, + owner: this.owner + })).data + smartAccountsList = smartAccountsList.filter((smartAccount: ISmartAccount) => { return accountIndex === smartAccount.index }) + if (smartAccountsList.length === 0) + throw new Error('Failed to get smart account address') + this.smartAccountInfo = smartAccountsList[0] + return this.smartAccountInfo.smartAccountAddress } catch (error) { - console.error(`Failed to get smart account address: ${error}`); + Logger.error(`Failed to get smart account address: ${error}`); throw error } } - async getInitCode(accountIndex: number = 0): Promise { + private async setInitCode(accountIndex: number = 0): Promise { this.initCode = ethers.utils.hexConcat([ this.factory.address, this.factory.interface.encodeFunctionData('deployCounterFactualAccount', [ @@ -131,6 +184,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart * @returns */ getExecuteCallData(to: string, value: BigNumberish, data: BytesLike): string { + this.isInitialized() this.isProxyDefined() const executeCallData = this.proxy.interface.encodeFunctionData('executeCall', [to, value, data]) return executeCallData @@ -143,12 +197,16 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart * @returns */ getExecuteBatchCallData(to: Array, value: Array, data: Array): string { + this.isInitialized() this.isProxyDefined() const executeBatchCallData = this.proxy.interface.encodeFunctionData('executeBatchCall', [to, value, data]) return executeBatchCallData } async buildUserOp(transactions: Transaction[], overrides?: Overrides): Promise> { + this.isInitialized() + // TODO: validate to, value and data fields + // TODO: validate overrides if supplied const to = transactions.map((element: Transaction) => element.to) const data = transactions.map((element: Transaction) => element.data ?? '0x') const value = transactions.map((element: Transaction) => element.value ?? BigNumber.from('0')) @@ -161,15 +219,16 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart callData = this.getExecuteBatchCallData(to, value, data) } const nonce = await this.isAccountDeployed(this.address) ? await this.nonce() : BigNumber.from(0) - + let userOp: Partial = { sender: this.address, nonce, initCode: nonce.eq(0) ? this.initCode : '0x', callData: callData - } + } - userOp = await this.estimateUserOpGas(userOp, overrides), + userOp = await this.estimateUserOpGas(userOp, overrides) + Logger.log('userOp after estimation ', userOp) userOp.paymasterAndData = await this.getPaymasterAndData(userOp) return userOp } diff --git a/packages/account/src/interfaces/IBiconomySmartAccount.ts b/packages/account/src/interfaces/IBiconomySmartAccount.ts index 2fce19646..ec32c0cf7 100644 --- a/packages/account/src/interfaces/IBiconomySmartAccount.ts +++ b/packages/account/src/interfaces/IBiconomySmartAccount.ts @@ -9,9 +9,13 @@ import { SCWTransactionResponse } from '@biconomy/node-client' import { Overrides } from '../utils/Types' +import { BigNumberish, BytesLike } from 'ethers' + export interface IBiconomySmartAccount { setAccountIndex(accountIndex: number): void + getExecuteCallData(to: string, value: BigNumberish, data: BytesLike): string + getExecuteBatchCallData(to: Array, value: Array, data: Array): string buildUserOp(transactions: Transaction[], overrides?: Overrides): Promise> getAllTokenBalances(balancesDto: BalancesDto): Promise getTotalBalanceInUsd(balancesDto: BalancesDto): Promise diff --git a/packages/account/src/utils/Constants.ts b/packages/account/src/utils/Constants.ts index b4a3fb98f..f3d57bbe6 100644 --- a/packages/account/src/utils/Constants.ts +++ b/packages/account/src/utils/Constants.ts @@ -1,14 +1,20 @@ import { ChainId } from '@biconomy/core-types' +import { EntrypointAddresses, BiconomyFactories, BiconomyImplementation } from './Types' -export const ENTRYPOINT_ADDRESSES = { - 'V0_0_5': '0x27a4Db290B89AE3373ce4313cBEaE72112Ae7Da9', - 'V0_0_6': '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - default: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789' +export const ENTRYPOINT_ADDRESSES: EntrypointAddresses = { + '0x27a4Db290B89AE3373ce4313cBEaE72112Ae7Da9': 'V0_0_5', + '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789': 'V0_0_6', + default: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789' // will always be latest { ENTRYPOINT_ADDRESSES } } -export const BICONOMY_FACTORY_ADDRESSES = { - 'V2_0_0': '0x000000F9eE1842Bb72F6BBDD75E6D3d4e3e9594C', - default: '0x000000F9eE1842Bb72F6BBDD75E6D3d4e3e9594C' +export const BICONOMY_FACTORY_ADDRESSES: BiconomyFactories = { + '0x000000F9eE1842Bb72F6BBDD75E6D3d4e3e9594C': 'V1_0_0', + default: '0x000000F9eE1842Bb72F6BBDD75E6D3d4e3e9594C' // will always be latest { BICONOMY_FACTORY_ADDRESSES } +} + +export const BICONOMY_IMPLEMENTATION_ADDRESSES: BiconomyImplementation = { + '0x00006b7e42e01957da540dc6a8f7c30c4d816af5': 'V1_0_0', + default: '0x00006b7e42e01957da540dc6a8f7c30c4d816af5' // will always be latest { BICONOMY_IMPLEMENTATION_ADDRESSES } } diff --git a/packages/account/src/utils/Types.ts b/packages/account/src/utils/Types.ts index e735cfd37..d072de706 100644 --- a/packages/account/src/utils/Types.ts +++ b/packages/account/src/utils/Types.ts @@ -5,6 +5,18 @@ import { IBundler } from '@biconomy/bundler' import { IPaymaster } from '@biconomy/paymaster' +export type EntrypointAddresses = { + [address: string]: string +} + +export type BiconomyFactories = { + [address: string]: string +} + +export type BiconomyImplementation = { + [address: string]: string +} + export type SmartAccountConfig = { entryPointAddress: string bundler?: IBundler diff --git a/packages/bundler/src/Bundler.ts b/packages/bundler/src/Bundler.ts index da40f014c..9c1be14d4 100644 --- a/packages/bundler/src/Bundler.ts +++ b/packages/bundler/src/Bundler.ts @@ -2,7 +2,7 @@ import { IBundler } from "./interfaces/IBundler"; import { UserOperation, ChainId } from '@biconomy/core-types' import { GetUserOperationResponse, GetUserOpByHashResponse, Bundlerconfig, UserOpResponse, EstimateUserOpGasResponse, UserOpReceipt, SendUserOpResponse, UserOpGasResponse, UserOpByHashResponse } from "./types/Types" import { resolveProperties } from 'ethers/lib/utils' -import { deepHexlify, getTimestampInSeconds, RPC_PROVIDER_URLS } from '@biconomy/common' +import { deepHexlify, getTimestampInSeconds, Logger, RPC_PROVIDER_URLS } from '@biconomy/common' import { HttpMethod, sendRequest } from './utils/httpRequests' import { transformUserOP } from './utils/HelperFunction' import { UserOpReceiptIntervals } from './utils/Constants' @@ -42,7 +42,7 @@ export class Bundler implements IBundler { } const userOperation = { ...dummpyUserop, ...userOp } userOp = transformUserOP(userOperation) - console.log('userOp sending for fee estimate ', userOp); + Logger.log('userOp sending for fee estimate ', userOp); const bundlerUrl = this.getBundlerUrl() diff --git a/packages/common/src/ContractsInstances.ts b/packages/common/src/ContractsInstances.ts new file mode 100644 index 000000000..21fd9ea74 --- /dev/null +++ b/packages/common/src/ContractsInstances.ts @@ -0,0 +1,61 @@ +import { SmartAccountType } from '@biconomy/core-types' +import { JsonRpcProvider } from '@ethersproject/providers' +import { + EntryPoint_v100, + EntryPoint_v100__factory, + SmartAccount_v100, SmartAccountFactory_v100, + SmartAccountFactory_v100__factory, + SmartAccount_v100__factory +} from './typechain' + +export type GetContractInstanceDto = { + smartAccountType: SmartAccountType, + version: string, + contractAddress: string, + provider: JsonRpcProvider +} + +export function getProxyContractInstance(contractInstanceDto: GetContractInstanceDto): SmartAccount_v100 { + const { smartAccountType, version, contractAddress, provider } = contractInstanceDto + switch (version) { + case '1.0.0': + if (smartAccountType === SmartAccountType.BICONOMY) { + return SmartAccount_v100__factory.connect(contractAddress, provider); + } + break; + default: + return SmartAccount_v100__factory.connect(contractAddress, provider); + } + throw new Error('Invalid version or smartAccountType provided for proxy contract instance'); + +} + +export function getFactoryContractInstance(contractInstanceDto: GetContractInstanceDto): SmartAccountFactory_v100 { + const { smartAccountType, version, contractAddress, provider } = contractInstanceDto + + switch (version) { + case '1.0.0': + if (smartAccountType === SmartAccountType.BICONOMY) { + return SmartAccountFactory_v100__factory.connect(contractAddress, provider) + } + break; + default: + return SmartAccountFactory_v100__factory.connect(contractAddress, provider) + } + throw new Error('Invalid version or smartAccountType provided for factory contract instance'); +} + +export function getEntryPointContractInstance(contractInstanceDto: GetContractInstanceDto): EntryPoint_v100 { + const { smartAccountType, version, contractAddress, provider } = contractInstanceDto + + switch (version) { + case 'V0_0_5': + if (smartAccountType === SmartAccountType.BICONOMY) { + return EntryPoint_v100__factory.connect(contractAddress, provider) + } + break; + default: + return EntryPoint_v100__factory.connect(contractAddress, provider) + } + throw new Error('Invalid version or smartAccountType provided for entrypoint contract instance'); +} \ No newline at end of file diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index d21dda3ac..f74c05006 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -7,3 +7,4 @@ export * from './httpRequests' export * from './typechain/index' export * from './Utils' export * from './Constants' +export * from './ContractsInstances' diff --git a/packages/core-types/src/SmartAccountTypes.ts b/packages/core-types/src/SmartAccountTypes.ts index 2287d03c1..24f6707c3 100644 --- a/packages/core-types/src/SmartAccountTypes.ts +++ b/packages/core-types/src/SmartAccountTypes.ts @@ -140,3 +140,9 @@ export type TransactionBatchDto = { transactions: Transaction[] chainId?: ChainId } + +export enum SmartAccountType { + CANDIDE, + BICONOMY, + SOUL +} \ No newline at end of file From 000378955257240e6619071d9ce97aae53e2feb8 Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Fri, 9 Jun 2023 16:11:08 +0500 Subject: [PATCH 2/9] versioning and logging --- packages/account/src/BiconomySmartAccount.ts | 8 +++++++- packages/common/src/ContractsInstances.ts | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/account/src/BiconomySmartAccount.ts b/packages/account/src/BiconomySmartAccount.ts index a32e3c4b2..a92a642d0 100644 --- a/packages/account/src/BiconomySmartAccount.ts +++ b/packages/account/src/BiconomySmartAccount.ts @@ -218,7 +218,13 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart } else { callData = this.getExecuteBatchCallData(to, value, data) } - const nonce = await this.isAccountDeployed(this.address) ? await this.nonce() : BigNumber.from(0) + + let nonce = BigNumber.from(0) + try { + nonce = await this.nonce() + } catch (error) { + // Not throwing this error as nonce would be 0 if this.nonce() throw exception, which is expected flow for undeployed account + } let userOp: Partial = { sender: this.address, diff --git a/packages/common/src/ContractsInstances.ts b/packages/common/src/ContractsInstances.ts index 21fd9ea74..5298cf4f8 100644 --- a/packages/common/src/ContractsInstances.ts +++ b/packages/common/src/ContractsInstances.ts @@ -18,7 +18,7 @@ export type GetContractInstanceDto = { export function getProxyContractInstance(contractInstanceDto: GetContractInstanceDto): SmartAccount_v100 { const { smartAccountType, version, contractAddress, provider } = contractInstanceDto switch (version) { - case '1.0.0': + case 'V1_0_0': if (smartAccountType === SmartAccountType.BICONOMY) { return SmartAccount_v100__factory.connect(contractAddress, provider); } @@ -34,7 +34,7 @@ export function getFactoryContractInstance(contractInstanceDto: GetContractInsta const { smartAccountType, version, contractAddress, provider } = contractInstanceDto switch (version) { - case '1.0.0': + case 'V1_0_0': if (smartAccountType === SmartAccountType.BICONOMY) { return SmartAccountFactory_v100__factory.connect(contractAddress, provider) } From d47e911c43f1ec1203aa4a1ff58b692f76f4baee Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Mon, 12 Jun 2023 13:11:43 +0500 Subject: [PATCH 3/9] fixes in signUserOp call and providers urls update --- packages/account/src/BaseAccount.ts | 2 +- packages/account/src/BiconomySmartAccount.ts | 1 - packages/account/src/index.ts | 1 + packages/common/src/Constants.ts | 16 ++++++++-------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/account/src/BaseAccount.ts b/packages/account/src/BaseAccount.ts index 58f7ba28a..cb2c4fda2 100644 --- a/packages/account/src/BaseAccount.ts +++ b/packages/account/src/BaseAccount.ts @@ -246,7 +246,7 @@ export abstract class SmartAccount implements ISmartAccount { */ async sendUserOp(userOp: Partial): Promise { let userOperation = await this.signUserOp(userOp) - const bundlerResponse = await this.sendUserOp(userOperation) + const bundlerResponse = await this.sendSignedUserOp(userOperation) return bundlerResponse } diff --git a/packages/account/src/BiconomySmartAccount.ts b/packages/account/src/BiconomySmartAccount.ts index a92a642d0..4ddc5eb39 100644 --- a/packages/account/src/BiconomySmartAccount.ts +++ b/packages/account/src/BiconomySmartAccount.ts @@ -133,7 +133,6 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart } async setAccountIndex(accountIndex: number): Promise { - this.isInitialized() this.accountIndex = accountIndex this.address = await this.getSmartAccountAddress(accountIndex) await this.setContractsState() diff --git a/packages/account/src/index.ts b/packages/account/src/index.ts index 022cd41ec..a75e2469f 100644 --- a/packages/account/src/index.ts +++ b/packages/account/src/index.ts @@ -2,3 +2,4 @@ export * from './interfaces/IBaseAccount' export * from './utils/Types' export * from './BaseAccount' export * from './BiconomySmartAccount' +export * from './utils/Constants' diff --git a/packages/common/src/Constants.ts b/packages/common/src/Constants.ts index 74fd20a1b..a892701d7 100644 --- a/packages/common/src/Constants.ts +++ b/packages/common/src/Constants.ts @@ -3,15 +3,15 @@ import { ChainId } from '@biconomy/core-types' export const NODE_CLIENT_URL = 'https://sdk-backend.prod.biconomy.io/v1' export const RPC_PROVIDER_URLS: { [key in ChainId]?: string } = { - [ChainId.MAINNET]: 'https://ethereum.publicnode.com', - [ChainId.GOERLI]: 'https://ethereum-goerli.publicnode.com', - [ChainId.POLYGON_MUMBAI] : 'https://polygon-mumbai-bor.publicnode.com', - [ChainId.POLYGON_MAINNET] : 'https://polygon-bor.publicnode.com', + [ChainId.MAINNET]: 'https://rpc.ankr.com/eth', + [ChainId.GOERLI]: 'https://rpc.ankr.com/eth_goerli', + [ChainId.POLYGON_MUMBAI] : 'https://rpc.ankr.com/polygon_mumbai', + [ChainId.POLYGON_MAINNET] : 'https://rpc.ankr.com/polygon', [ChainId.BSC_TESTNET] : 'https://endpoints.omniatech.io/v1/bsc/testnet/public', - [ChainId.BSC_MAINNET] : 'https://bsc.meowrpc.com', - [ChainId.POLYGON_ZKEVM_TESTNET] : 'https://rpc.ankr.com/arbitrum', - [ChainId.POLYGON_ZKEVM_MAINNET] : 'https://rpc.ankr.com/arbitrum', + [ChainId.BSC_MAINNET] : 'https://rpc.ankr.com/bsc', + [ChainId.POLYGON_ZKEVM_TESTNET] : 'https://rpc.public.zkevm-test.net', + [ChainId.POLYGON_ZKEVM_MAINNET] : 'https://rpc.ankr.com/polygon_zkevm', [ChainId.ARBITRUM_GOERLI_TESTNET] : 'https://goerli-rollup.arbitrum.io/rpc', [ChainId.ARBITRUM_ONE_MAINNET] : 'https://rpc.ankr.com/arbitrum', [ChainId.ARBITRUM_NOVA_MAINNET] : 'https://nova.arbitrum.io/rpc' -}; \ No newline at end of file +} \ No newline at end of file From 3a0bd521f5ed3af06e2d4b845e2f12e1f4ce3a4e Mon Sep 17 00:00:00 2001 From: livingrockrises <90545960+livingrockrises@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:41:48 +0530 Subject: [PATCH 4/9] chore: update rebuild.sh --- rebuild.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rebuild.sh b/rebuild.sh index f0a33f933..cea255429 100755 --- a/rebuild.sh +++ b/rebuild.sh @@ -3,6 +3,18 @@ rm -rf package-lock.json rm -rf yarn.lock rm -rf node_modules +rm -rf packages/account/node_modules +rm -rf packages/account/package-lock.json +rm -rf packages/account/dist + +rm -rf packages/bundler/node_modules +rm -rf packages/bundler/package-lock.json +rm -rf packages/bundler/dist + +rm -rf packages/paymaster/node_modules +rm -rf packages/paymaster/package-lock.json +rm -rf packages/paymaster/dist + rm -rf packages/account-abstraction/node_modules rm -rf packages/account-abstraction/package-lock.json rm -rf packages/account-abstraction/dist From 999ba923133e3554cebd73ac61bc789ac0b9ac52 Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Mon, 12 Jun 2023 18:19:06 +0500 Subject: [PATCH 5/9] review changes implementation --- packages/account/src/BaseAccount.ts | 2 +- packages/account/src/BiconomySmartAccount.ts | 26 ++++++++++++-------- packages/account/src/utils/Constants.ts | 22 +++++++++++------ packages/common/src/ContractsInstances.ts | 6 ++--- packages/core-types/src/SmartAccountTypes.ts | 4 +-- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/packages/account/src/BaseAccount.ts b/packages/account/src/BaseAccount.ts index cb2c4fda2..b127600fd 100644 --- a/packages/account/src/BaseAccount.ts +++ b/packages/account/src/BaseAccount.ts @@ -30,7 +30,7 @@ export abstract class SmartAccount implements ISmartAccount { } - setEntrypointAddress(entryPointAddress: string){ + setEntryPointAddress(entryPointAddress: string){ this.smartAccountConfig.entryPointAddress = entryPointAddress } diff --git a/packages/account/src/BiconomySmartAccount.ts b/packages/account/src/BiconomySmartAccount.ts index 239e04b17..d9b0c1390 100644 --- a/packages/account/src/BiconomySmartAccount.ts +++ b/packages/account/src/BiconomySmartAccount.ts @@ -6,9 +6,9 @@ import { NODE_CLIENT_URL, RPC_PROVIDER_URLS, SmartAccountFactory_v100, - getEntryPointContractInstance, - getFactoryContractInstance, - getProxyContractInstance + getEntryPointContract, + getSAFactoryContract, + getSAProxyContract } from '@biconomy/common' import { BiconomySmartAccountConfig, Overrides } from './utils/Types' import { UserOperation, Transaction, SmartAccountType } from '@biconomy/core-types' @@ -25,7 +25,7 @@ import { SmartAccountsResponse, SCWTransactionResponse } from '@biconomy/node-client' -import { ENTRYPOINT_ADDRESSES, BICONOMY_FACTORY_ADDRESSES, BICONOMY_IMPLEMENTATION_ADDRESSES } from './utils/Constants' +import { ENTRYPOINT_ADDRESSES, BICONOMY_FACTORY_ADDRESSES, BICONOMY_IMPLEMENTATION_ADDRESSES, DEFAULT_ENTRYPOINT_ADDRESS } from './utils/Constants' export class BiconomySmartAccount extends SmartAccount implements IBiconomySmartAccount { private factory!: SmartAccountFactory_v100 @@ -47,7 +47,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart nodeClientUrl } = biconomySmartAccountConfig - const _entryPointAddress = entryPointAddress ?? ENTRYPOINT_ADDRESSES.default + const _entryPointAddress = entryPointAddress ?? DEFAULT_ENTRYPOINT_ADDRESS super({ bundler, entryPointAddress: _entryPointAddress @@ -89,41 +89,47 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart private isInitialized(): boolean{ if (!this.isInited) - throw new Error('BiconomySmartAccount is not initialized. Please call BiconomySmartAccount.init() before interacting with any other function') + throw new Error('BiconomySmartAccount is not initialized. Please call init() on BiconomySmartAccount before interacting with any other function') return true } private setProxyContractState(){ + if ( !BICONOMY_IMPLEMENTATION_ADDRESSES[this.smartAccountInfo.implementationAddress] ) + throw new Error('Could not find attach implementation address again your smart account. Please generate support ticket for further investegation.') const proxyInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: BICONOMY_IMPLEMENTATION_ADDRESSES[this.address], contractAddress: this.address, provider: this.provider } - this.proxy = getProxyContractInstance(proxyInstanceDto) + this.proxy = getSAProxyContract(proxyInstanceDto) } private setEntryPointContractState(){ const _entryPointAddress = this.smartAccountInfo.entryPointAddress - this.setEntrypointAddress(_entryPointAddress) + this.setEntryPointAddress(_entryPointAddress) + if ( !ENTRYPOINT_ADDRESSES[_entryPointAddress] ) + throw new Error('Could not find attach entrypoint address again your smart account. Please generate support ticket for further investegation.') const entryPointInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: ENTRYPOINT_ADDRESSES[_entryPointAddress], contractAddress: _entryPointAddress, provider: this.provider } - this.entryPoint = getEntryPointContractInstance(entryPointInstanceDto) + this.entryPoint = getEntryPointContract(entryPointInstanceDto) } private setFactoryContractState(){ const _factoryAddress = this.smartAccountInfo.factoryAddress + if ( !BICONOMY_FACTORY_ADDRESSES[_factoryAddress] ) + throw new Error('Could not find attach factory address again your smart account. Please generate support ticket for further investegation.') const factoryInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: BICONOMY_FACTORY_ADDRESSES[_factoryAddress], contractAddress: _factoryAddress, provider: this.provider } - this.factory = getFactoryContractInstance(factoryInstanceDto) + this.factory = getSAFactoryContract(factoryInstanceDto) } private async setContractsState() { diff --git a/packages/account/src/utils/Constants.ts b/packages/account/src/utils/Constants.ts index f3d57bbe6..542df05a2 100644 --- a/packages/account/src/utils/Constants.ts +++ b/packages/account/src/utils/Constants.ts @@ -1,21 +1,29 @@ import { ChainId } from '@biconomy/core-types' import { EntrypointAddresses, BiconomyFactories, BiconomyImplementation } from './Types' + + // will always be latest entrypoint address +export const DEFAULT_ENTRYPOINT_ADDRESS = '0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789' export const ENTRYPOINT_ADDRESSES: EntrypointAddresses = { - '0x27a4Db290B89AE3373ce4313cBEaE72112Ae7Da9': 'V0_0_5', - '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789': 'V0_0_6', - default: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789' // will always be latest { ENTRYPOINT_ADDRESSES } + '0x27a4db290b89ae3373ce4313cbeae72112ae7da9': 'V0_0_5', + '0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789': 'V0_0_6' } + +// will always be latest factory address +export const DEFAULT_BICONOMY_FACTORY_ADDRESS = '0x000000f9ee1842bb72f6bbdd75e6d3d4e3e9594c' export const BICONOMY_FACTORY_ADDRESSES: BiconomyFactories = { - '0x000000F9eE1842Bb72F6BBDD75E6D3d4e3e9594C': 'V1_0_0', - default: '0x000000F9eE1842Bb72F6BBDD75E6D3d4e3e9594C' // will always be latest { BICONOMY_FACTORY_ADDRESSES } + '0x000000f9ee1842bb72f6bbdd75e6d3d4e3e9594c': 'V1_0_0' } + + export const BICONOMY_IMPLEMENTATION_ADDRESSES: BiconomyImplementation = { - '0x00006b7e42e01957da540dc6a8f7c30c4d816af5': 'V1_0_0', - default: '0x00006b7e42e01957da540dc6a8f7c30c4d816af5' // will always be latest { BICONOMY_IMPLEMENTATION_ADDRESSES } + '0x00006b7e42e01957da540dc6a8f7c30c4d816af5': 'V1_0_0' } +// will always be latest implementation address +export const DEFAULT_BICONOMY_IMPLEMENTATION_ADDRESS = '0x00006b7e42e01957da540dc6a8f7c30c4d816af5' + export const EIP1559_UNSUPPORTED_NETWORKS: Array = [97, 56, 1442, 1101] diff --git a/packages/common/src/ContractsInstances.ts b/packages/common/src/ContractsInstances.ts index 5298cf4f8..8b2dd2730 100644 --- a/packages/common/src/ContractsInstances.ts +++ b/packages/common/src/ContractsInstances.ts @@ -15,7 +15,7 @@ export type GetContractInstanceDto = { provider: JsonRpcProvider } -export function getProxyContractInstance(contractInstanceDto: GetContractInstanceDto): SmartAccount_v100 { +export function getSAProxyContract(contractInstanceDto: GetContractInstanceDto): SmartAccount_v100 { const { smartAccountType, version, contractAddress, provider } = contractInstanceDto switch (version) { case 'V1_0_0': @@ -30,7 +30,7 @@ export function getProxyContractInstance(contractInstanceDto: GetContractInstanc } -export function getFactoryContractInstance(contractInstanceDto: GetContractInstanceDto): SmartAccountFactory_v100 { +export function getSAFactoryContract(contractInstanceDto: GetContractInstanceDto): SmartAccountFactory_v100 { const { smartAccountType, version, contractAddress, provider } = contractInstanceDto switch (version) { @@ -45,7 +45,7 @@ export function getFactoryContractInstance(contractInstanceDto: GetContractInsta throw new Error('Invalid version or smartAccountType provided for factory contract instance'); } -export function getEntryPointContractInstance(contractInstanceDto: GetContractInstanceDto): EntryPoint_v100 { +export function getEntryPointContract(contractInstanceDto: GetContractInstanceDto): EntryPoint_v100 { const { smartAccountType, version, contractAddress, provider } = contractInstanceDto switch (version) { diff --git a/packages/core-types/src/SmartAccountTypes.ts b/packages/core-types/src/SmartAccountTypes.ts index 24f6707c3..82e62b32f 100644 --- a/packages/core-types/src/SmartAccountTypes.ts +++ b/packages/core-types/src/SmartAccountTypes.ts @@ -142,7 +142,5 @@ export type TransactionBatchDto = { } export enum SmartAccountType { - CANDIDE, - BICONOMY, - SOUL + BICONOMY } \ No newline at end of file From f1c9cd510121c06991d03973e2e6a3e0c1d9217b Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Wed, 14 Jun 2023 14:49:52 +0500 Subject: [PATCH 6/9] review changes --- packages/account/src/BiconomySmartAccount.ts | 16 +++++++++------- .../src/interfaces/IBiconomySmartAccount.ts | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/account/src/BiconomySmartAccount.ts b/packages/account/src/BiconomySmartAccount.ts index d9b0c1390..10fddd1a2 100644 --- a/packages/account/src/BiconomySmartAccount.ts +++ b/packages/account/src/BiconomySmartAccount.ts @@ -77,7 +77,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart this.isSignerDefined() this.owner = await this.signer.getAddress() this.chainId = await this.provider.getNetwork().then((net) => net.chainId) - await this.setAccountIndex(accountIndex) + await this.initializeAccountAtIndex(accountIndex) this.isInited = true } catch (error) { Logger.error(`Failed to call init: ${error}`); @@ -89,13 +89,13 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart private isInitialized(): boolean{ if (!this.isInited) - throw new Error('BiconomySmartAccount is not initialized. Please call init() on BiconomySmartAccount before interacting with any other function') + throw new Error('BiconomySmartAccount is not initialized. Please call init() on BiconomySmartAccount instance before interacting with any other function') return true } private setProxyContractState(){ if ( !BICONOMY_IMPLEMENTATION_ADDRESSES[this.smartAccountInfo.implementationAddress] ) - throw new Error('Could not find attach implementation address again your smart account. Please generate support ticket for further investegation.') + throw new Error('Could not find attach implementation address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') const proxyInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: BICONOMY_IMPLEMENTATION_ADDRESSES[this.address], @@ -109,7 +109,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart const _entryPointAddress = this.smartAccountInfo.entryPointAddress this.setEntryPointAddress(_entryPointAddress) if ( !ENTRYPOINT_ADDRESSES[_entryPointAddress] ) - throw new Error('Could not find attach entrypoint address again your smart account. Please generate support ticket for further investegation.') + throw new Error('Could not find attach entrypoint address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') const entryPointInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: ENTRYPOINT_ADDRESSES[_entryPointAddress], @@ -122,7 +122,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart private setFactoryContractState(){ const _factoryAddress = this.smartAccountInfo.factoryAddress if ( !BICONOMY_FACTORY_ADDRESSES[_factoryAddress] ) - throw new Error('Could not find attach factory address again your smart account. Please generate support ticket for further investegation.') + throw new Error('Could not find attach factory address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') const factoryInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: BICONOMY_FACTORY_ADDRESSES[_factoryAddress], @@ -138,7 +138,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart this.setFactoryContractState() } - async setAccountIndex(accountIndex: number): Promise { + async initializeAccountAtIndex(accountIndex: number): Promise { this.accountIndex = accountIndex this.address = await this.getSmartAccountAddress(accountIndex) await this.setContractsState() @@ -152,9 +152,11 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart chainId: this.chainId, owner: this.owner })).data + if ( !smartAccountsList ) + throw new Error('Failed to get smart account address. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') smartAccountsList = smartAccountsList.filter((smartAccount: ISmartAccount) => { return accountIndex === smartAccount.index }) if (smartAccountsList.length === 0) - throw new Error('Failed to get smart account address') + throw new Error('Failed to get smart account address. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') this.smartAccountInfo = smartAccountsList[0] return this.smartAccountInfo.smartAccountAddress } catch (error) { diff --git a/packages/account/src/interfaces/IBiconomySmartAccount.ts b/packages/account/src/interfaces/IBiconomySmartAccount.ts index ec32c0cf7..ac177ce83 100644 --- a/packages/account/src/interfaces/IBiconomySmartAccount.ts +++ b/packages/account/src/interfaces/IBiconomySmartAccount.ts @@ -13,7 +13,7 @@ import { BigNumberish, BytesLike } from 'ethers' export interface IBiconomySmartAccount { - setAccountIndex(accountIndex: number): void + initializeAccountAtIndex(accountIndex: number): void getExecuteCallData(to: string, value: BigNumberish, data: BytesLike): string getExecuteBatchCallData(to: Array, value: Array, data: Array): string buildUserOp(transactions: Transaction[], overrides?: Overrides): Promise> From 2804582cd04c2ccc0dfa7fb8f2029f262fbf132b Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Wed, 14 Jun 2023 17:46:13 +0500 Subject: [PATCH 7/9] added dummy userOp values for gas estimation --- packages/bundler/src/Bundler.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/bundler/src/Bundler.ts b/packages/bundler/src/Bundler.ts index 9c1be14d4..d20be40d6 100644 --- a/packages/bundler/src/Bundler.ts +++ b/packages/bundler/src/Bundler.ts @@ -30,15 +30,16 @@ export class Bundler implements IBundler { * @returns Promise */ async estimateUserOpGas(userOp: UserOperation): Promise { - // TODO: will be removed once full userOp requirement is removed from bundler side + // bundler require these dummy values for estimation + // TODO: dapp/dev need to take dummy signature as well that we will pass to bundler. as signature depends on smart contract implementation const dummpyUserop = { - callGasLimit: '0', - verificationGasLimit: '0', - preVerificationGas: '0', + callGasLimit: '90000', + verificationGasLimit: '3000000', + preVerificationGas: '46856', maxFeePerGas: '0', maxPriorityFeePerGas: '0', paymasterAndData: '0x', - signature: '0x' + signature: '0x73c3ac716c487ca34bb858247b5ccf1dc354fbaabdd089af3b2ac8e78ba85a4959a2d76250325bd67c11771c31fccda87c33ceec17cc0de912690521bb95ffcb1b' } const userOperation = { ...dummpyUserop, ...userOp } userOp = transformUserOP(userOperation) From 88da9b2fc7d10da339c5134e99659f8704fd100b Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Fri, 16 Jun 2023 15:22:52 +0500 Subject: [PATCH 8/9] typo sorted --- packages/account/src/BiconomySmartAccount.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/account/src/BiconomySmartAccount.ts b/packages/account/src/BiconomySmartAccount.ts index 10fddd1a2..5970c5e26 100644 --- a/packages/account/src/BiconomySmartAccount.ts +++ b/packages/account/src/BiconomySmartAccount.ts @@ -95,7 +95,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart private setProxyContractState(){ if ( !BICONOMY_IMPLEMENTATION_ADDRESSES[this.smartAccountInfo.implementationAddress] ) - throw new Error('Could not find attach implementation address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') + throw new Error('Could not find attached implementation address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') const proxyInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: BICONOMY_IMPLEMENTATION_ADDRESSES[this.address], @@ -109,7 +109,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart const _entryPointAddress = this.smartAccountInfo.entryPointAddress this.setEntryPointAddress(_entryPointAddress) if ( !ENTRYPOINT_ADDRESSES[_entryPointAddress] ) - throw new Error('Could not find attach entrypoint address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') + throw new Error('Could not find attached entrypoint address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') const entryPointInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: ENTRYPOINT_ADDRESSES[_entryPointAddress], @@ -122,7 +122,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart private setFactoryContractState(){ const _factoryAddress = this.smartAccountInfo.factoryAddress if ( !BICONOMY_FACTORY_ADDRESSES[_factoryAddress] ) - throw new Error('Could not find attach factory address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') + throw new Error('Could not find attached factory address against your smart account. Please raise an issue on https://github.com/bcnmy/biconomy-client-sdk for further investigation.') const factoryInstanceDto = { smartAccountType: SmartAccountType.BICONOMY, version: BICONOMY_FACTORY_ADDRESSES[_factoryAddress], From 46ab5dc3133f3ce39180b7d268a8f8be011ef45c Mon Sep 17 00:00:00 2001 From: talhamalik883 Date: Fri, 16 Jun 2023 16:19:36 +0500 Subject: [PATCH 9/9] isInitied variable name updated --- packages/account/src/BiconomySmartAccount.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/account/src/BiconomySmartAccount.ts b/packages/account/src/BiconomySmartAccount.ts index 5970c5e26..040d0a845 100644 --- a/packages/account/src/BiconomySmartAccount.ts +++ b/packages/account/src/BiconomySmartAccount.ts @@ -33,7 +33,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart private accountIndex!: number private address!: string private smartAccountInfo!: ISmartAccount - private isInited!: boolean + private _isInitialised!: boolean constructor(readonly biconomySmartAccountConfig: BiconomySmartAccountConfig) { const { @@ -78,7 +78,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart this.owner = await this.signer.getAddress() this.chainId = await this.provider.getNetwork().then((net) => net.chainId) await this.initializeAccountAtIndex(accountIndex) - this.isInited = true + this._isInitialised = true } catch (error) { Logger.error(`Failed to call init: ${error}`); throw error @@ -88,7 +88,7 @@ export class BiconomySmartAccount extends SmartAccount implements IBiconomySmart } private isInitialized(): boolean{ - if (!this.isInited) + if (!this._isInitialised) throw new Error('BiconomySmartAccount is not initialized. Please call init() on BiconomySmartAccount instance before interacting with any other function') return true }