diff --git a/src/assets/abi/GnosisSafeProxyFactory.ts b/src/assets/abi/GnosisSafeProxyFactory.ts new file mode 100644 index 0000000000..07e073e9f9 --- /dev/null +++ b/src/assets/abi/GnosisSafeProxyFactory.ts @@ -0,0 +1,71 @@ +const GnosisSafeProxyFactoryAbi = [ + { + anonymous: false, + inputs: [ + { indexed: false, internalType: 'contract GnosisSafeProxy', name: 'proxy', type: 'address' }, + { indexed: false, internalType: 'address', name: 'singleton', type: 'address' }, + ], + name: 'ProxyCreation', + type: 'event', + }, + { + inputs: [ + { internalType: 'address', name: '_singleton', type: 'address' }, + { internalType: 'bytes', name: 'initializer', type: 'bytes' }, + { internalType: 'uint256', name: 'saltNonce', type: 'uint256' }, + ], + name: 'calculateCreateProxyWithNonceAddress', + outputs: [{ internalType: 'contract GnosisSafeProxy', name: 'proxy', type: 'address' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'singleton', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'createProxy', + outputs: [{ internalType: 'contract GnosisSafeProxy', name: 'proxy', type: 'address' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_singleton', type: 'address' }, + { internalType: 'bytes', name: 'initializer', type: 'bytes' }, + { internalType: 'uint256', name: 'saltNonce', type: 'uint256' }, + { internalType: 'contract IProxyCreationCallback', name: 'callback', type: 'address' }, + ], + name: 'createProxyWithCallback', + outputs: [{ internalType: 'contract GnosisSafeProxy', name: 'proxy', type: 'address' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_singleton', type: 'address' }, + { internalType: 'bytes', name: 'initializer', type: 'bytes' }, + { internalType: 'uint256', name: 'saltNonce', type: 'uint256' }, + ], + name: 'createProxyWithNonce', + outputs: [{ internalType: 'contract GnosisSafeProxy', name: 'proxy', type: 'address' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'proxyCreationCode', + outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [], + name: 'proxyRuntimeCode', + outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], + stateMutability: 'pure', + type: 'function', + }, +] as const; + +export default GnosisSafeProxyFactoryAbi; diff --git a/src/hooks/DAO/useBuildDAOTx.ts b/src/hooks/DAO/useBuildDAOTx.ts index 55f5577eca..0788e9452f 100644 --- a/src/hooks/DAO/useBuildDAOTx.ts +++ b/src/hooks/DAO/useBuildDAOTx.ts @@ -25,6 +25,7 @@ const useBuildDAOTx = () => { votesERC20MasterCopy, keyValuePairs, fractalRegistry, + safeFactory, }, } = useNetworkConfig(); @@ -49,7 +50,6 @@ const useBuildDAOTx = () => { } const { multiSendContract, - safeFactoryContract, safeSingletonContract, linearVotingMasterCopyContract, linearVotingERC721MasterCopyContract, @@ -94,7 +94,6 @@ const useBuildDAOTx = () => { const buildrerBaseContracts: BaseContracts = { fractalModuleMasterCopyContract: fractalModuleMasterCopyContract.asSigner, - safeFactoryContract: safeFactoryContract.asSigner, safeSingletonContract: safeSingletonContract.asSigner, multisigFreezeGuardMasterCopyContract: multisigFreezeGuardMasterCopyContract.asSigner, multiSendContract: multiSendContract.asSigner, @@ -115,6 +114,7 @@ const useBuildDAOTx = () => { votesERC20MasterCopy, keyValuePairs, fractalRegistry, + safeFactory, parentAddress, parentTokenAddress, ); @@ -166,6 +166,7 @@ const useBuildDAOTx = () => { votesERC20MasterCopy, keyValuePairs, fractalRegistry, + safeFactory, ], ); diff --git a/src/hooks/DAO/useDeployAzorius.ts b/src/hooks/DAO/useDeployAzorius.ts index 36a54ada62..2e9147bdc0 100644 --- a/src/hooks/DAO/useDeployAzorius.ts +++ b/src/hooks/DAO/useDeployAzorius.ts @@ -28,6 +28,7 @@ const useDeployAzorius = () => { votesERC20MasterCopy, keyValuePairs, fractalRegistry, + safeFactory, }, addressPrefix, } = useNetworkConfig(); @@ -52,7 +53,6 @@ const useDeployAzorius = () => { } const { multiSendContract, - safeFactoryContract, safeSingletonContract, linearVotingMasterCopyContract, linearVotingERC721MasterCopyContract, @@ -78,7 +78,6 @@ const useDeployAzorius = () => { const builderBaseContracts: BaseContracts = { fractalModuleMasterCopyContract: fractalModuleMasterCopyContract.asProvider, - safeFactoryContract: safeFactoryContract.asProvider, safeSingletonContract: safeSingletonContract.asProvider, multisigFreezeGuardMasterCopyContract: multisigFreezeGuardMasterCopyContract.asProvider, multiSendContract: multiSendContract.asProvider, @@ -99,6 +98,7 @@ const useDeployAzorius = () => { votesERC20MasterCopy, keyValuePairs, fractalRegistry, + safeFactory, undefined, undefined, ); @@ -161,6 +161,7 @@ const useDeployAzorius = () => { votesERC20MasterCopy, keyValuePairs, fractalRegistry, + safeFactory, ], ); diff --git a/src/models/TxBuilderFactory.ts b/src/models/TxBuilderFactory.ts index 0b77d858ef..f1bea3a919 100644 --- a/src/models/TxBuilderFactory.ts +++ b/src/models/TxBuilderFactory.ts @@ -1,5 +1,6 @@ import { ethers } from 'ethers'; -import { PublicClient, getAddress } from 'viem'; +import { PublicClient, getAddress, getContract } from 'viem'; +import GnosisSafeProxyFactoryAbi from '../assets/abi/GnosisSafeProxyFactory'; import { GnosisSafeL2 } from '../assets/typechain-types/usul/@gnosis.pm/safe-contracts/contracts'; import { GnosisSafeL2__factory } from '../assets/typechain-types/usul/factories/@gnosis.pm/safe-contracts/contracts'; import { getRandomBytes } from '../helpers'; @@ -33,6 +34,7 @@ export class TxBuilderFactory extends BaseTxBuilder { private votesERC20MasterCopyAddress: string; private keyValuePairsAddress: string; private fractalRegistryAddress: string; + private gnosisSafeProxyFactoryAddress: string; constructor( signerOrProvider: ethers.Signer | any, @@ -45,6 +47,7 @@ export class TxBuilderFactory extends BaseTxBuilder { votesERC20MasterCopyAddress: string, keyValuePairsAddress: string, fractalRegistryAddress: string, + gnosisSafeProxyFactoryAddress: string, parentAddress?: string, parentTokenAddress?: string, ) { @@ -64,6 +67,7 @@ export class TxBuilderFactory extends BaseTxBuilder { this.votesERC20MasterCopyAddress = votesERC20MasterCopyAddress; this.keyValuePairsAddress = keyValuePairsAddress; this.fractalRegistryAddress = fractalRegistryAddress; + this.gnosisSafeProxyFactoryAddress = gnosisSafeProxyFactoryAddress; } public setSafeContract(safeAddress: string) { @@ -72,9 +76,14 @@ export class TxBuilderFactory extends BaseTxBuilder { } public async setupSafeData(): Promise { + const safeProxyFactoryContract = getContract({ + abi: GnosisSafeProxyFactoryAbi, + address: getAddress(this.gnosisSafeProxyFactoryAddress), + client: this.publicClient, + }); const { predictedSafeAddress, createSafeTx } = await safeData( this.baseContracts.multiSendContract, - this.baseContracts.safeFactoryContract, + safeProxyFactoryContract, this.baseContracts.safeSingletonContract, this.daoData as SafeMultisigDAO, this.saltNum, diff --git a/src/models/helpers/safeData.ts b/src/models/helpers/safeData.ts index 622c229eba..471031b154 100644 --- a/src/models/helpers/safeData.ts +++ b/src/models/helpers/safeData.ts @@ -1,4 +1,3 @@ -import { GnosisSafeProxyFactory } from '@fractal-framework/fractal-contracts'; import { getCreate2Address, zeroAddress, @@ -9,16 +8,19 @@ import { encodeFunctionData, isHex, hexToBigInt, + GetContractReturnType, + PublicClient, } from 'viem'; import GnosisSafeL2Abi from '../../assets/abi/GnosisSafeL2'; +import GnosisSafeProxyFactoryAbi from '../../assets/abi/GnosisSafeProxyFactory'; import { MultiSend } from '../../assets/typechain-types/usul'; import { GnosisSafeL2 } from '../../assets/typechain-types/usul/@gnosis.pm/safe-contracts/contracts'; -import { buildContractCall } from '../../helpers/crypto'; +import { buildContractCallViem } from '../../helpers/crypto'; import { SafeMultisigDAO } from '../../types'; export const safeData = async ( multiSendContract: MultiSend, - safeFactoryContract: GnosisSafeProxyFactory, + safeFactoryContract: GetContractReturnType, safeSingletonContract: GnosisSafeL2, daoData: SafeMultisigDAO, saltNum: bigint, @@ -44,7 +46,7 @@ export const safeData = async ( abi: GnosisSafeL2Abi, }); - const safeFactoryContractProxyCreationCode = await safeFactoryContract.proxyCreationCode(); + const safeFactoryContractProxyCreationCode = await safeFactoryContract.read.proxyCreationCode(); if (!isHex(safeFactoryContractProxyCreationCode)) { throw new Error('Error retrieving proxy creation code from Safe Factory Contract '); } @@ -68,8 +70,9 @@ export const safeData = async ( ), }); - const createSafeTx = buildContractCall( - safeFactoryContract, + const createSafeTx = buildContractCallViem( + GnosisSafeProxyFactoryAbi, + safeFactoryContract.address, 'createProxyWithNonce', [safeSingletonContract.address, createSafeCalldata, saltNum], 0, diff --git a/src/types/contract.ts b/src/types/contract.ts index 3dd200a263..37ac829a02 100644 --- a/src/types/contract.ts +++ b/src/types/contract.ts @@ -1,5 +1,4 @@ import { - GnosisSafeProxyFactory, ModuleProxyFactory, FractalModule, MultisigFreezeGuard, @@ -21,7 +20,6 @@ export type ContractConnection = { export interface BaseContracts { fractalModuleMasterCopyContract: FractalModule; - safeFactoryContract: GnosisSafeProxyFactory; safeSingletonContract: GnosisSafeL2; multisigFreezeGuardMasterCopyContract: MultisigFreezeGuard; multiSendContract: MultiSend; diff --git a/src/types/fractal.ts b/src/types/fractal.ts index 68edeac593..d321d395a0 100644 --- a/src/types/fractal.ts +++ b/src/types/fractal.ts @@ -1,6 +1,5 @@ import { FractalModule, - GnosisSafeProxyFactory, ModuleProxyFactory, LinearERC20Voting, Azorius, @@ -331,7 +330,6 @@ export interface NodeHierarchy { export interface FractalContracts { multiSendContract: ContractConnection; - safeFactoryContract: ContractConnection; fractalAzoriusMasterCopyContract: ContractConnection; linearVotingMasterCopyContract: ContractConnection; linearVotingERC721MasterCopyContract: ContractConnection;