diff --git a/src/helpers/crypto.ts b/src/helpers/crypto.ts index a7a3359ed0..0718ce498b 100644 --- a/src/helpers/crypto.ts +++ b/src/helpers/crypto.ts @@ -15,7 +15,6 @@ import { encodeFunctionData, Abi, } from 'viem'; -import { ContractConnection } from '../types'; import { MetaTransaction, SafePostTransaction, SafeTransaction } from '../types/transaction'; export interface SafeSignature { @@ -236,10 +235,3 @@ const encodeMetaTransaction = (tx: MetaTransaction): string => { export const encodeMultiSend = (txs: MetaTransaction[]): string => { return '0x' + txs.map(tx => encodeMetaTransaction(tx)).join(''); }; - -/** - * TODO: Remove getEventRPC usage as whole - */ -export function getEventRPC(connection: ContractConnection): T { - return connection.asProvider; -} diff --git a/src/hooks/DAO/useBuildDAOTx.ts b/src/hooks/DAO/useBuildDAOTx.ts index 0788e9452f..d244a69cd2 100644 --- a/src/hooks/DAO/useBuildDAOTx.ts +++ b/src/hooks/DAO/useBuildDAOTx.ts @@ -26,6 +26,7 @@ const useBuildDAOTx = () => { keyValuePairs, fractalRegistry, safeFactory, + zodiacModuleProxyFactory, }, } = useNetworkConfig(); @@ -54,7 +55,6 @@ const useBuildDAOTx = () => { linearVotingMasterCopyContract, linearVotingERC721MasterCopyContract, fractalAzoriusMasterCopyContract, - zodiacModuleProxyFactoryContract, fractalModuleMasterCopyContract, multisigFreezeGuardMasterCopyContract, azoriusFreezeGuardMasterCopyContract, @@ -100,7 +100,6 @@ const useBuildDAOTx = () => { freezeERC20VotingMasterCopyContract: freezeERC20VotingMasterCopyContract.asSigner, freezeERC721VotingMasterCopyContract: freezeERC721VotingMasterCopyContract.asSigner, freezeMultisigVotingMasterCopyContract: freezeMultisigVotingMasterCopyContract.asSigner, - zodiacModuleProxyFactoryContract: zodiacModuleProxyFactoryContract.asSigner, }; const txBuilderFactory = new TxBuilderFactory( @@ -115,6 +114,7 @@ const useBuildDAOTx = () => { keyValuePairs, fractalRegistry, safeFactory, + zodiacModuleProxyFactory, parentAddress, parentTokenAddress, ); @@ -167,6 +167,7 @@ const useBuildDAOTx = () => { keyValuePairs, fractalRegistry, safeFactory, + zodiacModuleProxyFactory, ], ); diff --git a/src/hooks/DAO/useDeployAzorius.ts b/src/hooks/DAO/useDeployAzorius.ts index 2e9147bdc0..70ac1dc968 100644 --- a/src/hooks/DAO/useDeployAzorius.ts +++ b/src/hooks/DAO/useDeployAzorius.ts @@ -29,6 +29,7 @@ const useDeployAzorius = () => { keyValuePairs, fractalRegistry, safeFactory, + zodiacModuleProxyFactory, }, addressPrefix, } = useNetworkConfig(); @@ -57,7 +58,6 @@ const useDeployAzorius = () => { linearVotingMasterCopyContract, linearVotingERC721MasterCopyContract, fractalAzoriusMasterCopyContract, - zodiacModuleProxyFactoryContract, fractalModuleMasterCopyContract, multisigFreezeGuardMasterCopyContract, azoriusFreezeGuardMasterCopyContract, @@ -84,7 +84,6 @@ const useDeployAzorius = () => { freezeERC20VotingMasterCopyContract: freezeERC20VotingMasterCopyContract.asProvider, freezeERC721VotingMasterCopyContract: freezeERC721VotingMasterCopyContract.asProvider, freezeMultisigVotingMasterCopyContract: freezeMultisigVotingMasterCopyContract.asProvider, - zodiacModuleProxyFactoryContract: zodiacModuleProxyFactoryContract.asProvider, }; const txBuilderFactory = new TxBuilderFactory( @@ -99,6 +98,7 @@ const useDeployAzorius = () => { keyValuePairs, fractalRegistry, safeFactory, + zodiacModuleProxyFactory, undefined, undefined, ); @@ -162,6 +162,7 @@ const useDeployAzorius = () => { keyValuePairs, fractalRegistry, safeFactory, + zodiacModuleProxyFactory, ], ); diff --git a/src/hooks/utils/useMasterCopy.ts b/src/hooks/utils/useMasterCopy.ts index 6775ed0257..c50f6a9b20 100644 --- a/src/hooks/utils/useMasterCopy.ts +++ b/src/hooks/utils/useMasterCopy.ts @@ -1,15 +1,19 @@ -import { ModuleProxyFactory } from '@fractal-framework/fractal-contracts'; -import { Contract } from 'ethers'; import { useCallback } from 'react'; -import { Address, zeroAddress } from 'viem'; -import { getEventRPC } from '../../helpers'; +import { Address, getContract, zeroAddress } from 'viem'; +import { usePublicClient } from 'wagmi'; +import ModuleProxyFactoryAbi from '../../assets/abi/ModuleProxyFactory'; import { useFractal } from '../../providers/App/AppProvider'; +import { useNetworkConfig } from '../../providers/NetworkConfig/NetworkConfigProvider'; import { CacheExpiry, CacheKeys } from './cache/cacheDefaults'; import { useLocalStorage } from './cache/useLocalStorage'; export function useMasterCopy() { const { getValue, setValue } = useLocalStorage(); const { baseContracts } = useFractal(); + const { + contracts: { zodiacModuleProxyFactory }, + } = useNetworkConfig(); + const publicClient = usePublicClient(); const isOzLinearVoting = useCallback( (masterCopyAddress: Address) => @@ -49,39 +53,60 @@ export function useMasterCopy() { ); const getMasterCopyAddress = useCallback( - async function (contract: Contract, proxyAddress: Address): Promise<[Address, string | null]> { + async function (proxyAddress: Address): Promise { + if (!publicClient) { + return [zeroAddress, null] as const; + } + const cachedValue = getValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress); - if (cachedValue) return [cachedValue, null] as const; + if (cachedValue) { + return [cachedValue, null] as const; + } - const filter = contract.filters.ModuleProxyCreation(proxyAddress, null); - return contract.queryFilter(filter).then(proxiesCreated => { - // @dev to prevent redundant queries, cache the master copy address as AddressZero if no proxies were created - if (proxiesCreated.length === 0) { - setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, zeroAddress, CacheExpiry.ONE_WEEK); - return [zeroAddress, 'No proxies created'] as const; - } - const masterCopyAddress = proxiesCreated[0].args!.masterCopy; - setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, masterCopyAddress); - return [masterCopyAddress, null] as const; + const moduleProxyFactoryContract = getContract({ + abi: ModuleProxyFactoryAbi, + address: zodiacModuleProxyFactory, + client: publicClient, }); + + return moduleProxyFactoryContract.getEvents + .ModuleProxyCreation({ proxy: proxyAddress }) + .then(proxiesCreated => { + // @dev to prevent redundant queries, cache the master copy address as AddressZero if no proxies were created + if (proxiesCreated.length === 0) { + setValue( + CacheKeys.MASTER_COPY_PREFIX + proxyAddress, + zeroAddress, + CacheExpiry.ONE_WEEK, + ); + return [zeroAddress, 'No proxies created'] as const; + } + + const masterCopyAddress = proxiesCreated[0].args.masterCopy; + if (!masterCopyAddress) { + return [zeroAddress, 'No master copy address'] as const; + } + + setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, masterCopyAddress); + return [masterCopyAddress, null] as const; + }) + .catch(() => { + return [zeroAddress, 'error'] as const; + }); }, - [getValue, setValue], + [getValue, publicClient, setValue, zodiacModuleProxyFactory], ); const getZodiacModuleProxyMasterCopyData = useCallback( async function (proxyAddress: Address) { let masterCopyAddress: Address = zeroAddress; let error; - if (baseContracts) { - // TODO after removing this moduleproxyfactorycontract from basecontracts, kill getEventRPC - const contract = getEventRPC( - baseContracts?.zodiacModuleProxyFactoryContract, - ); - [masterCopyAddress, error] = await getMasterCopyAddress(contract, proxyAddress); - if (error) { - console.error(error); - } + + [masterCopyAddress, error] = await getMasterCopyAddress(proxyAddress); + if (error) { + console.error(error); } + return { address: masterCopyAddress, isOzLinearVoting: isOzLinearVoting(masterCopyAddress), @@ -96,13 +121,12 @@ export function useMasterCopy() { [ getMasterCopyAddress, isAzorius, - isFractalModule, isERC721FreezeVoting, + isFractalModule, isMultisigFreezeGuard, isMultisigFreezeVoting, isOzLinearVoting, isOzLinearVotingERC721, - baseContracts, ], ); diff --git a/src/models/AzoriusTxBuilder.ts b/src/models/AzoriusTxBuilder.ts index 7fad01c0e3..89b38a82a9 100644 --- a/src/models/AzoriusTxBuilder.ts +++ b/src/models/AzoriusTxBuilder.ts @@ -22,6 +22,7 @@ import { PublicClient, getContract, } from 'viem'; +import ModuleProxyFactoryAbi from '../assets/abi/ModuleProxyFactory'; import VotesERC20Abi from '../assets/abi/VotesERC20'; import VotesERC20WrapperAbi from '../assets/abi/VotesERC20Wrapper'; import { GnosisSafeL2 } from '../assets/typechain-types/usul/@gnosis.pm/safe-contracts/contracts'; @@ -60,6 +61,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { private votesERC20WrapperMasterCopyAddress: string; private votesERC20MasterCopyAddress: string; + private moduleProxyFactoryAddress: Address; private tokenNonce: bigint; private strategyNonce: bigint; @@ -75,6 +77,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { safeContract: GnosisSafeL2, votesERC20WrapperMasterCopyAddress: string, votesERC20MasterCopyAddress: string, + moduleProxyFactoryAddress: Address, parentAddress?: Address, parentTokenAddress?: Address, ) { @@ -97,6 +100,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { this.votesERC20WrapperMasterCopyAddress = votesERC20WrapperMasterCopyAddress; this.votesERC20MasterCopyAddress = votesERC20MasterCopyAddress; + this.moduleProxyFactoryAddress = moduleProxyFactoryAddress; if (daoData.votingStrategyType === VotingStrategyType.LINEAR_ERC20) { daoData = daoData as AzoriusERC20DAO; @@ -192,8 +196,9 @@ export class AzoriusTxBuilder extends BaseTxBuilder { } public buildCreateTokenTx(): SafeTransaction { - return buildContractCall( - this.baseContracts.zodiacModuleProxyFactoryContract, + return buildContractCallViem( + ModuleProxyFactoryAbi, + this.moduleProxyFactoryAddress, 'deployModule', [this.votesERC20MasterCopyAddress, this.encodedSetupTokenData, this.tokenNonce], 0, @@ -204,8 +209,9 @@ export class AzoriusTxBuilder extends BaseTxBuilder { public buildDeployStrategyTx(): SafeTransaction { const daoData = this.daoData as AzoriusGovernanceDAO; - return buildContractCall( - this.baseContracts.zodiacModuleProxyFactoryContract, + return buildContractCallViem( + ModuleProxyFactoryAbi, + this.moduleProxyFactoryAddress, 'deployModule', [ daoData.votingStrategyType === VotingStrategyType.LINEAR_ERC20 @@ -220,8 +226,9 @@ export class AzoriusTxBuilder extends BaseTxBuilder { } public buildDeployAzoriusTx(): SafeTransaction { - return buildContractCall( - this.baseContracts.zodiacModuleProxyFactoryContract, + return buildContractCallViem( + ModuleProxyFactoryAbi, + this.moduleProxyFactoryAddress, 'deployModule', [ this.azoriusContracts!.fractalAzoriusMasterCopyContract.address, @@ -234,8 +241,9 @@ export class AzoriusTxBuilder extends BaseTxBuilder { } public buildDeployTokenClaim() { - return buildContractCall( - this.baseContracts.zodiacModuleProxyFactoryContract, + return buildContractCallViem( + ModuleProxyFactoryAbi, + this.moduleProxyFactoryAddress, 'deployModule', [ this.azoriusContracts!.claimingMasterCopyContract.address, @@ -264,8 +272,9 @@ export class AzoriusTxBuilder extends BaseTxBuilder { } public buildCreateTokenWrapperTx(): SafeTransaction { - return buildContractCall( - this.baseContracts.zodiacModuleProxyFactoryContract, + return buildContractCallViem( + ModuleProxyFactoryAbi, + this.moduleProxyFactoryAddress, 'deployModule', [this.votesERC20WrapperMasterCopyAddress, this.encodedSetupERC20WrapperData, this.tokenNonce], 0, @@ -301,7 +310,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { const tokenSalt = generateSalt(this.encodedSetupERC20WrapperData!, this.tokenNonce); this.predictedTokenAddress = getCreate2Address({ - from: getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), + from: this.moduleProxyFactoryAddress, salt: tokenSalt, bytecodeHash: keccak256(encodePacked(['bytes'], [tokenByteCodeLinear])), }); @@ -369,7 +378,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { const tokenSalt = generateSalt(this.encodedSetupTokenData!, this.tokenNonce); this.predictedTokenAddress = getCreate2Address({ - from: getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), + from: this.moduleProxyFactoryAddress, salt: tokenSalt, bytecodeHash: keccak256(encodePacked(['bytes'], [tokenByteCodeLinear])), }); @@ -408,7 +417,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { const tokenSalt = generateSalt(this.encodedSetupTokenClaimData!, this.claimNonce); this.predictedTokenClaimAddress = getCreate2Address({ - from: getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), + from: this.moduleProxyFactoryAddress, salt: tokenSalt, bytecodeHash: keccak256(encodePacked(['bytes'], [tokenByteCodeLinear])), }); @@ -461,7 +470,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { this.encodedStrategySetupData = encodedStrategySetupData; this.predictedStrategyAddress = getCreate2Address({ - from: getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), + from: this.moduleProxyFactoryAddress, salt: strategySalt, bytecodeHash: keccak256(encodePacked(['bytes'], [strategyByteCodeLinear])), }); @@ -508,7 +517,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { this.encodedStrategySetupData = encodedStrategySetupData; this.predictedStrategyAddress = getCreate2Address({ - from: getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), + from: this.moduleProxyFactoryAddress, salt: strategySalt, bytecodeHash: keccak256(encodePacked(['bytes'], [strategyByteCodeLinear])), }); @@ -548,7 +557,7 @@ export class AzoriusTxBuilder extends BaseTxBuilder { this.encodedSetupAzoriusData = encodedSetupAzoriusData; this.predictedAzoriusAddress = getCreate2Address({ - from: getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), + from: this.moduleProxyFactoryAddress, salt: azoriusSalt, bytecodeHash: keccak256(encodePacked(['bytes'], [azoriusByteCodeLinear])), }); diff --git a/src/models/DaoTxBuilder.ts b/src/models/DaoTxBuilder.ts index cda0b12a55..2e65ca68c5 100644 --- a/src/models/DaoTxBuilder.ts +++ b/src/models/DaoTxBuilder.ts @@ -36,6 +36,7 @@ export class DaoTxBuilder extends BaseTxBuilder { private readonly keyValuePairsAddress: string; private readonly fractalRegistryAddress: string; + private readonly moduleProxyFactoryAddress: string; constructor( signerOrProvider: ethers.Signer | any, @@ -49,6 +50,7 @@ export class DaoTxBuilder extends BaseTxBuilder { txBuilderFactory: TxBuilderFactory, keyValuePairsAddress: string, fractalRegistryAddress: string, + moduleProxyFactoryAddress: string, parentAddress?: string, parentTokenAddress?: string, parentStrategyType?: VotingStrategyType, @@ -73,6 +75,7 @@ export class DaoTxBuilder extends BaseTxBuilder { this.keyValuePairsAddress = keyValuePairsAddress; this.fractalRegistryAddress = fractalRegistryAddress; + this.moduleProxyFactoryAddress = moduleProxyFactoryAddress; // Prep fractal module txs for setting up subDAOs this.setFractalModuleTxs(); @@ -216,7 +219,7 @@ export class DaoTxBuilder extends BaseTxBuilder { private setFractalModuleTxs(): void { const { enableFractalModuleTx, deployFractalModuleTx }: FractalModuleData = fractalModuleData( this.baseContracts.fractalModuleMasterCopyContract, - this.baseContracts.zodiacModuleProxyFactoryContract, + getAddress(this.moduleProxyFactoryAddress), this.safeContract!, this.saltNum, this.parentAddress, diff --git a/src/models/FreezeGuardTxBuilder.ts b/src/models/FreezeGuardTxBuilder.ts index ba999c0e47..48875e604c 100644 --- a/src/models/FreezeGuardTxBuilder.ts +++ b/src/models/FreezeGuardTxBuilder.ts @@ -21,8 +21,9 @@ import { isHex, PublicClient, } from 'viem'; +import ModuleProxyFactoryAbi from '../assets/abi/ModuleProxyFactory'; import { GnosisSafeL2 } from '../assets/typechain-types/usul/@gnosis.pm/safe-contracts/contracts'; -import { buildContractCall } from '../helpers'; +import { buildContractCall, buildContractCallViem } from '../helpers'; import { BaseContracts, SafeTransaction, @@ -31,12 +32,7 @@ import { VotingStrategyType, } from '../types'; import { BaseTxBuilder } from './BaseTxBuilder'; -import { - buildDeployZodiacModuleTx, - generateContractByteCodeLinear, - generatePredictedModuleAddress, - generateSalt, -} from './helpers/utils'; +import { generateContractByteCodeLinear, generateSalt } from './helpers/utils'; export class FreezeGuardTxBuilder extends BaseTxBuilder { // Salt used to generate transactions @@ -60,6 +56,7 @@ export class FreezeGuardTxBuilder extends BaseTxBuilder { private parentStrategyType: VotingStrategyType | undefined; private parentStrategyAddress: Address | undefined; + private moduleProxyFactoryAddress: Address; constructor( signerOrProvider: any, @@ -69,6 +66,7 @@ export class FreezeGuardTxBuilder extends BaseTxBuilder { safeContract: GnosisSafeL2, saltNum: bigint, parentAddress: Address, + moduleProxyFactoryAddress: Address, parentTokenAddress?: Address, azoriusContracts?: AzoriusContracts, azoriusAddress?: Address, @@ -92,6 +90,7 @@ export class FreezeGuardTxBuilder extends BaseTxBuilder { this.strategyAddress = strategyAddress; this.parentStrategyType = parentStrategyType; this.parentStrategyAddress = parentStrategyAddress; + this.moduleProxyFactoryAddress = moduleProxyFactoryAddress; this.initFreezeVotesData(); } @@ -104,8 +103,9 @@ export class FreezeGuardTxBuilder extends BaseTxBuilder { } public buildDeployZodiacModuleTx(): SafeTransaction { - return buildContractCall( - this.baseContracts.zodiacModuleProxyFactoryContract, + return buildContractCallViem( + ModuleProxyFactoryAbi, + this.moduleProxyFactoryAddress, 'deployModule', [ this.freezeVotingType === ERC20FreezeVoting__factory @@ -156,11 +156,14 @@ export class FreezeGuardTxBuilder extends BaseTxBuilder { } public buildDeployFreezeGuardTx() { - return buildDeployZodiacModuleTx(this.baseContracts.zodiacModuleProxyFactoryContract, [ - this.getGuardMasterCopyAddress(), - this.freezeGuardCallData!, - this.saltNum, - ]); + return buildContractCallViem( + ModuleProxyFactoryAbi, + this.moduleProxyFactoryAddress, + 'deployModule', + [this.getGuardMasterCopyAddress(), this.freezeGuardCallData!, this.saltNum], + 0, + false, + ); } /** @@ -200,7 +203,7 @@ export class FreezeGuardTxBuilder extends BaseTxBuilder { ); this.freezeVotingAddress = getCreate2Address({ - from: getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), + from: this.moduleProxyFactoryAddress, salt: generateSalt(this.freezeVotingCallData!, this.saltNum), bytecodeHash: keccak256(encodePacked(['bytes'], [freezeVotingByteCodeLinear])), }); @@ -212,11 +215,11 @@ export class FreezeGuardTxBuilder extends BaseTxBuilder { ); const freezeGuardSalt = generateSalt(this.freezeGuardCallData!, this.saltNum); - this.freezeGuardAddress = generatePredictedModuleAddress( - getAddress(this.baseContracts.zodiacModuleProxyFactoryContract.address), - freezeGuardSalt, - freezeGuardByteCodeLinear, - ); + this.freezeGuardAddress = getCreate2Address({ + from: this.moduleProxyFactoryAddress, + salt: freezeGuardSalt, + bytecodeHash: keccak256(encodePacked(['bytes'], [freezeGuardByteCodeLinear])), + }); } private setFreezeGuardData() { diff --git a/src/models/TxBuilderFactory.ts b/src/models/TxBuilderFactory.ts index f1bea3a919..37c89b58de 100644 --- a/src/models/TxBuilderFactory.ts +++ b/src/models/TxBuilderFactory.ts @@ -35,6 +35,7 @@ export class TxBuilderFactory extends BaseTxBuilder { private keyValuePairsAddress: string; private fractalRegistryAddress: string; private gnosisSafeProxyFactoryAddress: string; + private moduleProxyFactoryAddress: string; constructor( signerOrProvider: ethers.Signer | any, @@ -48,6 +49,7 @@ export class TxBuilderFactory extends BaseTxBuilder { keyValuePairsAddress: string, fractalRegistryAddress: string, gnosisSafeProxyFactoryAddress: string, + moduleProxyFactoryAddress: string, parentAddress?: string, parentTokenAddress?: string, ) { @@ -68,6 +70,7 @@ export class TxBuilderFactory extends BaseTxBuilder { this.keyValuePairsAddress = keyValuePairsAddress; this.fractalRegistryAddress = fractalRegistryAddress; this.gnosisSafeProxyFactoryAddress = gnosisSafeProxyFactoryAddress; + this.moduleProxyFactoryAddress = moduleProxyFactoryAddress; } public setSafeContract(safeAddress: string) { @@ -113,6 +116,7 @@ export class TxBuilderFactory extends BaseTxBuilder { this, this.keyValuePairsAddress, this.fractalRegistryAddress, + this.moduleProxyFactoryAddress, this.parentAddress, this.parentTokenAddress, parentStrategyType, @@ -134,6 +138,7 @@ export class TxBuilderFactory extends BaseTxBuilder { this.safeContract!, this.saltNum, getAddress(this.parentAddress!), + getAddress(this.moduleProxyFactoryAddress), this.parentTokenAddress ? getAddress(this.parentTokenAddress) : undefined, this.azoriusContracts, azoriusAddress ? getAddress(azoriusAddress) : undefined, @@ -161,6 +166,7 @@ export class TxBuilderFactory extends BaseTxBuilder { this.safeContract!, this.votesERC20WrapperMasterCopyAddress, this.votesERC20MasterCopyAddress, + getAddress(this.moduleProxyFactoryAddress), this.parentAddress ? getAddress(this.parentAddress) : undefined, this.parentTokenAddress ? getAddress(this.parentTokenAddress) : undefined, ); diff --git a/src/models/helpers/fractalModuleData.ts b/src/models/helpers/fractalModuleData.ts index 3482f61f21..78cca40d4b 100644 --- a/src/models/helpers/fractalModuleData.ts +++ b/src/models/helpers/fractalModuleData.ts @@ -1,18 +1,19 @@ +import { FractalModule, FractalModule__factory } from '@fractal-framework/fractal-contracts'; import { - FractalModule, - FractalModule__factory, - ModuleProxyFactory, -} from '@fractal-framework/fractal-contracts'; -import { encodeAbiParameters, parseAbiParameters, getAddress, isHex } from 'viem'; + encodeAbiParameters, + parseAbiParameters, + getAddress, + isHex, + Address, + getCreate2Address, + keccak256, + encodePacked, +} from 'viem'; +import ModuleProxyFactoryAbi from '../../assets/abi/ModuleProxyFactory'; import { GnosisSafeL2 } from '../../assets/typechain-types/usul/@gnosis.pm/safe-contracts/contracts'; -import { buildContractCall } from '../../helpers/crypto'; +import { buildContractCall, buildContractCallViem } from '../../helpers/crypto'; import { SafeTransaction } from '../../types'; -import { - buildDeployZodiacModuleTx, - generateContractByteCodeLinear, - generatePredictedModuleAddress, - generateSalt, -} from './utils'; +import { generateContractByteCodeLinear, generateSalt } from './utils'; export interface FractalModuleData { predictedFractalModuleAddress: string; @@ -22,7 +23,7 @@ export interface FractalModuleData { export const fractalModuleData = ( fractalModuleMasterCopyContract: FractalModule, - zodiacModuleProxyFactoryContract: ModuleProxyFactory, + moduleProxyFactoryAddress: Address, safeContract: GnosisSafeL2, saltNum: bigint, parentAddress?: string, @@ -48,17 +49,22 @@ export const fractalModuleData = ( ); const fractalSalt = generateSalt(fractalModuleCalldata, saltNum); - const deployFractalModuleTx = buildDeployZodiacModuleTx(zodiacModuleProxyFactoryContract, [ - fractalModuleMasterCopyContract.address, - fractalModuleCalldata, - saltNum, - ]); - const predictedFractalModuleAddress = generatePredictedModuleAddress( - getAddress(zodiacModuleProxyFactoryContract.address), - fractalSalt, - fractalByteCodeLinear, + + const deployFractalModuleTx = buildContractCallViem( + ModuleProxyFactoryAbi, + moduleProxyFactoryAddress, + 'deployModule', + [fractalModuleMasterCopyContract.address, fractalModuleCalldata, saltNum], + 0, + false, ); + const predictedFractalModuleAddress = getCreate2Address({ + from: moduleProxyFactoryAddress, + salt: fractalSalt, + bytecodeHash: keccak256(encodePacked(['bytes'], [fractalByteCodeLinear])), + }); + const enableFractalModuleTx = buildContractCall( safeContract, 'enableModule', diff --git a/src/models/helpers/utils.ts b/src/models/helpers/utils.ts index a3a96a2388..d378dafedc 100644 --- a/src/models/helpers/utils.ts +++ b/src/models/helpers/utils.ts @@ -1,8 +1,4 @@ -// Prefix and postfix strings come from Zodiac contracts -import { ModuleProxyFactory } from '@fractal-framework/fractal-contracts'; -import { Address, Hash, getCreate2Address, keccak256, encodePacked } from 'viem'; -import { buildContractCall } from '../../helpers/crypto'; -import { SafeTransaction } from '../../types'; +import { Address, Hash, keccak256, encodePacked } from 'viem'; /** * These hardcoded values were taken from @@ -17,22 +13,3 @@ export const generateSalt = (calldata: Hash, saltNum: bigint): Hash => { encodePacked(['bytes32', 'uint256'], [keccak256(encodePacked(['bytes'], [calldata])), saltNum]), ); }; - -export const generatePredictedModuleAddress = ( - zodiacProxyAddress: Address, - salt: Hash, - byteCode: Hash, -): Address => { - return getCreate2Address({ - from: zodiacProxyAddress, - salt, - bytecodeHash: keccak256(encodePacked(['bytes'], [byteCode])), - }); -}; - -export const buildDeployZodiacModuleTx = ( - zodiacProxyFactoryContract: ModuleProxyFactory, - params: (string | bigint)[], -): SafeTransaction => { - return buildContractCall(zodiacProxyFactoryContract, 'deployModule', params, 0, false); -}; diff --git a/src/types/contract.ts b/src/types/contract.ts index 37ac829a02..aca182226e 100644 --- a/src/types/contract.ts +++ b/src/types/contract.ts @@ -1,5 +1,4 @@ import { - ModuleProxyFactory, FractalModule, MultisigFreezeGuard, MultisigFreezeVoting, @@ -26,5 +25,4 @@ export interface BaseContracts { freezeERC20VotingMasterCopyContract: ERC20FreezeVoting; freezeERC721VotingMasterCopyContract: ERC721FreezeVoting; freezeMultisigVotingMasterCopyContract: MultisigFreezeVoting; - zodiacModuleProxyFactoryContract: ModuleProxyFactory; } diff --git a/src/types/fractal.ts b/src/types/fractal.ts index d321d395a0..f1cbd99e7a 100644 --- a/src/types/fractal.ts +++ b/src/types/fractal.ts @@ -1,6 +1,5 @@ import { FractalModule, - ModuleProxyFactory, LinearERC20Voting, Azorius, AzoriusFreezeGuard, @@ -334,7 +333,6 @@ export interface FractalContracts { linearVotingMasterCopyContract: ContractConnection; linearVotingERC721MasterCopyContract: ContractConnection; safeSingletonContract: ContractConnection; - zodiacModuleProxyFactoryContract: ContractConnection; fractalModuleMasterCopyContract: ContractConnection; multisigFreezeGuardMasterCopyContract: ContractConnection; azoriusFreezeGuardMasterCopyContract: ContractConnection;