diff --git a/src/libs/deployless/simulateDeployCall.ts b/src/libs/deployless/simulateDeployCall.ts index fea594276..3d8439453 100644 --- a/src/libs/deployless/simulateDeployCall.ts +++ b/src/libs/deployless/simulateDeployCall.ts @@ -12,7 +12,7 @@ import { DeploylessMode, fromDescriptor } from './deployless' // on the given network export async function getSASupport( provider: JsonRpcProvider -): Promise<{ addressMatches: boolean; supportsStateOverride: boolean }> { +): Promise<{ addressMatches: boolean }> { const smartAccount = await getSmartAccount( [ { @@ -31,7 +31,6 @@ export async function getSASupport( mode: DeploylessMode.StateOverride } const deployless = fromDescriptor(provider, AmbireFactory, true) - let supportsStateOverride = true const result = await deployless .call( 'deployAndExecute', @@ -50,12 +49,10 @@ export async function getSASupport( // if there's an error, return the zero address indicating that // our smart accounts will most likely not work on this chain - supportsStateOverride = false return [ZeroAddress] }) return { - addressMatches: result[0] === smartAccount.addr, - supportsStateOverride + addressMatches: result[0] === smartAccount.addr } } diff --git a/src/libs/deployless/supportsStateOverride.ts b/src/libs/deployless/supportsStateOverride.ts new file mode 100644 index 000000000..e7d9a8781 --- /dev/null +++ b/src/libs/deployless/supportsStateOverride.ts @@ -0,0 +1,42 @@ +import { JsonRpcProvider, ZeroAddress } from 'ethers' + +import Estimation from '../../../contracts/compiled/Estimation.json' +import { FEE_COLLECTOR } from '../../consts/addresses' +import { getEOAEstimationStateOverride } from '../estimate/estimateEOA' +import { EOA_SIMULATION_NONCE } from '../portfolio/getOnchainBalances' +import { Deployless, DeploylessMode } from './deployless' + +export async function doesItSupportStateOverride(provider: JsonRpcProvider) { + const estimator = new Deployless(provider, Estimation.abi, Estimation.bin, Estimation.binRuntime) + + // try to write to the state in deployless mode + const accAddr = '0xc1e7354c7d11d95BDa4adf2A3Fd8984E1ddE7aCc' + const result = await estimator + .call( + 'estimateEoa', + [ + accAddr, + [ + accAddr, + EOA_SIMULATION_NONCE, + [['0x3e2D734349654166a2Ad92CaB2437A76a70B650a', 1n, '0x']], + '0x' + ], + '0x', + [accAddr], + FEE_COLLECTOR, + ZeroAddress + ], + { + from: '0x0000000000000000000000000000000000000001', + blockTag: 'latest', + mode: DeploylessMode.StateOverride, + stateToOverride: getEOAEstimationStateOverride(accAddr) + } + ) + .catch(() => { + return 'not working' + }) + + return result !== 'not working' +} diff --git a/src/libs/estimate/estimateEOA.ts b/src/libs/estimate/estimateEOA.ts index 626b19f0f..6faa1763d 100644 --- a/src/libs/estimate/estimateEOA.ts +++ b/src/libs/estimate/estimateEOA.ts @@ -19,7 +19,7 @@ const abiCoder = new AbiCoder() // this is the state override we use for the EOA when // estimating through Estimation.sol -function getEOAEstimationStateOverride(accountAddr: string) { +export function getEOAEstimationStateOverride(accountAddr: string) { return { [accountAddr]: { code: AmbireAccount.binRuntime, diff --git a/src/libs/networks/networks.ts b/src/libs/networks/networks.ts index 88bfb7f29..938b3eae5 100644 --- a/src/libs/networks/networks.ts +++ b/src/libs/networks/networks.ts @@ -14,6 +14,7 @@ import { RPCProviders } from '../../interfaces/provider' import { Bundler } from '../../services/bundlers/bundler' import { getRpcProvider } from '../../services/provider' import { getSASupport } from '../deployless/simulateDeployCall' +import { doesItSupportStateOverride } from '../deployless/supportsStateOverride' // bnb, fantom, metis const relayerAdditionalNetworks = [56n, 250n, 1088n] @@ -84,12 +85,14 @@ export async function getNetworkInfo( retryRequest(() => provider.getCode(SINGLETON)), retryRequest(() => provider.getCode(AMBIRE_ACCOUNT_FACTORY)), retryRequest(() => getSASupport(provider)), + retryRequest(() => doesItSupportStateOverride(provider)), Bundler.isNetworkSupported(fetch, chainId).catch(() => false) // retryRequest(() => provider.getCode(ERC_4337_ENTRYPOINT)), ]).catch((e: Error) => raiseFlagged(e, ['0x', '0x', { addressMatches: false, supportsStateOverride: false }]) ) - const [singletonCode, factoryCode, saSupport, is4337enabled] = responses + const [singletonCode, factoryCode, saSupport, supportsStateOverride, is4337enabled] = + responses const areContractsDeployed = factoryCode !== '0x' // const has4337 = entryPointCode !== '0x' && hasBundler const predefinedNetwork = predefinedNetworks.find((net) => net.chainId === chainId) @@ -98,7 +101,7 @@ export async function getNetworkInfo( // - or we can't do the simulation with this RPC but we have the factory // deployed on the network const supportsAmbire = - saSupport.addressMatches || (!saSupport.supportsStateOverride && areContractsDeployed) + saSupport.addressMatches || (!supportsStateOverride && areContractsDeployed) networkInfo = { ...networkInfo, hasSingleton: singletonCode !== '0x', @@ -107,7 +110,7 @@ export async function getNetworkInfo( rpcNoStateOverride: predefinedNetwork && predefinedNetwork.rpcNoStateOverride === true ? true - : !saSupport.supportsStateOverride, + : !supportsStateOverride, erc4337: { enabled: predefinedNetwork ? predefinedNetwork.erc4337.enabled : is4337enabled, hasPaymaster: predefinedNetwork ? predefinedNetwork.erc4337.hasPaymaster : false