Skip to content

Commit

Permalink
Remove all instances of MultiSend objects from FractalContracts, Base…
Browse files Browse the repository at this point in the history
…Contracs, useSafeContracts, etc
  • Loading branch information
adamgall committed May 6, 2024
1 parent 801934a commit 800009c
Show file tree
Hide file tree
Showing 15 changed files with 134 additions and 91 deletions.
11 changes: 11 additions & 0 deletions src/assets/abi/MultiSendCallOnly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const MultiSendCallOnlyAbi = [
{
inputs: [{ internalType: 'bytes', name: 'transactions', type: 'bytes' }],
name: 'multiSend',
outputs: [],
stateMutability: 'payable',
type: 'function',
},
] as const;

export default MultiSendCallOnlyAbi;
4 changes: 2 additions & 2 deletions src/helpers/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,6 @@ const encodeMetaTransaction = (tx: MetaTransaction): string => {
return encoded.slice(2);
};

export const encodeMultiSend = (txs: MetaTransaction[]): string => {
return '0x' + txs.map(tx => encodeMetaTransaction(tx)).join('');
export const encodeMultiSend = (txs: MetaTransaction[]): Hex => {
return `0x${txs.map(tx => encodeMetaTransaction(tx)).join('')}`;
};
51 changes: 29 additions & 22 deletions src/hooks/DAO/proposal/useSubmitProposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@ import { Azorius } from '@fractal-framework/fractal-contracts';
import axios from 'axios';
import { useCallback, useMemo, useState } from 'react';
import { toast } from 'react-toastify';
import { isAddress, getAddress, encodeAbiParameters, parseAbiParameters, isHex } from 'viem';
import {
isAddress,
getAddress,
encodeAbiParameters,
parseAbiParameters,
isHex,
encodeFunctionData,
} from 'viem';
import { useWalletClient } from 'wagmi';
import MultiSendCallOnlyAbi from '../../../assets/abi/MultiSendCallOnly';
import { ADDRESS_MULTISIG_METADATA, SENTINEL_ADDRESS } from '../../../constants/common';
import { buildSafeAPIPost, encodeMultiSend } from '../../../helpers';
import { logError } from '../../../helpers/errorLogging';
Expand All @@ -14,7 +22,6 @@ import { useEthersSigner } from '../../../providers/Ethers/hooks/useEthersSigner
import { useNetworkConfig } from '../../../providers/NetworkConfig/NetworkConfigProvider';
import { MetaTransaction, ProposalExecuteData, CreateProposalMetadata } from '../../../types';
import { buildSafeApiUrl, getAzoriusModuleFromModules } from '../../../utils';
import useSafeContracts from '../../safe/useSafeContracts';
import useSignerOrProvider from '../../utils/useSignerOrProvider';
import { useFractalModules } from '../loaders/useFractalModules';
import { useDAOProposals } from '../loaders/useProposals';
Expand Down Expand Up @@ -58,7 +65,6 @@ export default function useSubmitProposal() {
guardContracts: { freezeVotingContractAddress },
governanceContracts: { ozLinearVotingContractAddress, erc721LinearVotingContractAddress },
} = useFractal();
const baseContracts = useSafeContracts();
const safeAPI = useSafeAPI();

const globalAzoriusContract = useMemo(() => {
Expand All @@ -75,7 +81,12 @@ export default function useSubmitProposal() {

const lookupModules = useFractalModules();
const signerOrProvider = useSignerOrProvider();
const { chain, safeBaseURL, addressPrefix } = useNetworkConfig();
const {
chain,
safeBaseURL,
addressPrefix,
contracts: { multisend: multiSendCallOnly },
} = useNetworkConfig();
const ipfsClient = useIPFSClient();

const submitMultisigProposal = useCallback(
Expand All @@ -88,10 +99,9 @@ export default function useSubmitProposal() {
successCallback,
safeAddress,
}: ISubmitProposal) => {
if (!proposalData || !baseContracts || !walletClient) {
if (!proposalData || !walletClient) {
return;
}
const { multiSendContract } = baseContracts;

const toastId = toast(pendingToastMessage, {
autoClose: false,
Expand Down Expand Up @@ -124,14 +134,15 @@ export default function useSubmitProposal() {
proposalData.calldatas.push(encodeAbiParameters(parseAbiParameters(['string']), [Hash]));
}

let to, value, data, operation: 0 | 1;
let to = proposalData.targets[0];
let value = proposalData.values[0];
let data = proposalData.calldatas[0];
let operation: 0 | 1 = 0;

if (proposalData.targets.length > 1) {
if (!multiSendContract) {
toast.dismiss(toastId);
return;
}
// Need to wrap it in Multisend function call
to = getAddress(multiSendContract.asProvider.address);
to = multiSendCallOnly;
value = 0n;

const tempData = proposalData.targets.map((target, index) => {
return {
Expand All @@ -142,21 +153,17 @@ export default function useSubmitProposal() {
} as MetaTransaction;
});

data = multiSendContract.asProvider.interface.encodeFunctionData('multiSend', [
encodeMultiSend(tempData),
]);
data = encodeFunctionData({
abi: MultiSendCallOnlyAbi,
functionName: 'multiSend',
args: [encodeMultiSend(tempData)],
});

if (!isHex(data)) {
throw new Error('Error encoding proposal data');
}

operation = 1;
} else {
// Single transaction to post
to = proposalData.targets[0];
value = BigInt(proposalData.values[0]);
data = proposalData.calldatas[0];
operation = 0;
}

await axios.post(
Expand Down Expand Up @@ -186,10 +193,10 @@ export default function useSubmitProposal() {
},
[
addressPrefix,
baseContracts,
chain.id,
ipfsClient,
loadDAOProposals,
multiSendCallOnly,
safeBaseURL,
signerOrProvider,
walletClient,
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/DAO/useBuildDAOTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const useBuildDAOTx = () => {
safeFactory,
safe: safeSingleton,
zodiacModuleProxyFactory,
multisend: multiSendCallOnly,
},
} = useNetworkConfig();

Expand All @@ -51,7 +52,6 @@ const useBuildDAOTx = () => {
return;
}
const {
multiSendContract,
linearVotingMasterCopyContract,
linearVotingERC721MasterCopyContract,
fractalAzoriusMasterCopyContract,
Expand Down Expand Up @@ -95,7 +95,6 @@ const useBuildDAOTx = () => {
const buildrerBaseContracts: BaseContracts = {
fractalModuleMasterCopyContract: fractalModuleMasterCopyContract.asSigner,
multisigFreezeGuardMasterCopyContract: multisigFreezeGuardMasterCopyContract.asSigner,
multiSendContract: multiSendContract.asSigner,
freezeERC20VotingMasterCopyContract: freezeERC20VotingMasterCopyContract.asSigner,
freezeERC721VotingMasterCopyContract: freezeERC721VotingMasterCopyContract.asSigner,
freezeMultisigVotingMasterCopyContract: freezeMultisigVotingMasterCopyContract.asSigner,
Expand All @@ -115,6 +114,7 @@ const useBuildDAOTx = () => {
safeFactory,
safeSingleton,
zodiacModuleProxyFactory,
multiSendCallOnly,
parentAddress,
parentTokenAddress,
);
Expand Down Expand Up @@ -169,6 +169,7 @@ const useBuildDAOTx = () => {
safeFactory,
safeSingleton,
zodiacModuleProxyFactory,
multiSendCallOnly,
],
);

Expand Down
24 changes: 14 additions & 10 deletions src/hooks/DAO/useCreateSubDAOProposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { isHex, getAddress, encodeFunctionData } from 'viem';
import FractalRegistryAbi from '../../assets/abi/FractalRegistry';
import MultiSendCallOnlyAbi from '../../assets/abi/MultiSendCallOnly';
import { useFractal } from '../../providers/App/AppProvider';
import { useNetworkConfig } from '../../providers/NetworkConfig/NetworkConfigProvider';
import { SafeMultisigDAO, AzoriusGovernance, AzoriusERC20DAO, AzoriusERC721DAO } from '../../types';
Expand All @@ -11,7 +12,6 @@ import useSubmitProposal from './proposal/useSubmitProposal';
import useBuildDAOTx from './useBuildDAOTx';

export const useCreateSubDAOProposal = () => {
const { baseContracts } = useFractal();
const { t } = useTranslation(['daoCreate', 'proposal', 'proposalMetadata']);

const { submitProposal, pendingCreateTx } = useSubmitProposal();
Expand All @@ -22,7 +22,7 @@ export const useCreateSubDAOProposal = () => {
governance,
} = useFractal();
const {
contracts: { fractalRegistry },
contracts: { fractalRegistry, multisend: multiSendCallOnly },
} = useNetworkConfig();
const azoriusGovernance = governance as AzoriusGovernance;
const proposeDao = useCallback(
Expand All @@ -32,10 +32,9 @@ export const useCreateSubDAOProposal = () => {
successCallback: (addressPrefix: string, daoAddress: string) => void,
) => {
const propose = async () => {
if (!baseContracts || !daoAddress) {
if (!daoAddress) {
return;
}
const { multiSendContract } = baseContracts;

const builtSafeTx = await build(daoData, daoAddress, azoriusGovernance.votesToken?.address);
if (!builtSafeTx) {
Expand All @@ -44,10 +43,15 @@ export const useCreateSubDAOProposal = () => {

const { safeTx, predictedSafeAddress } = builtSafeTx;

const encodedMultisend = multiSendContract.asProvider.interface.encodeFunctionData(
'multiSend',
[safeTx],
);
if (!isHex(safeTx)) {
throw new Error('Built safeTx is not a hex string');
}

const encodedMultisend = encodeFunctionData({
abi: MultiSendCallOnlyAbi,
functionName: 'multiSend',
args: [safeTx],
});

if (!isHex(encodedMultisend)) {
throw new Error('encodedMultisend data is not hex??');
Expand All @@ -60,7 +64,7 @@ export const useCreateSubDAOProposal = () => {
});

const proposalData: ProposalExecuteData = {
targets: [getAddress(multiSendContract.asProvider.address), fractalRegistry],
targets: [multiSendCallOnly, fractalRegistry],
values: [0n, 0n],
calldatas: [encodedMultisend, encodedDeclareSubDAO],
metaData: {
Expand All @@ -82,10 +86,10 @@ export const useCreateSubDAOProposal = () => {
},
[
azoriusGovernance.votesToken?.address,
baseContracts,
build,
daoAddress,
fractalRegistry,
multiSendCallOnly,
submitProposal,
t,
],
Expand Down
29 changes: 17 additions & 12 deletions src/hooks/DAO/useDeployAzorius.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { encodeFunctionData, getAddress, isHex } from 'viem';
import { encodeFunctionData, isHex } from 'viem';
import { usePublicClient } from 'wagmi';
import GnosisSafeL2Abi from '../../assets/abi/GnosisSafeL2';
import MultiSendCallOnlyAbi from '../../assets/abi/MultiSendCallOnly';
import { DAO_ROUTES } from '../../constants/routes';
import { TxBuilderFactory } from '../../models/TxBuilderFactory';
import { useFractal } from '../../providers/App/AppProvider';
Expand Down Expand Up @@ -32,6 +33,7 @@ const useDeployAzorius = () => {
safeFactory,
safe: safeSingleton,
zodiacModuleProxyFactory,
multisend: multiSendCallOnly,
},
addressPrefix,
} = useNetworkConfig();
Expand All @@ -55,7 +57,6 @@ const useDeployAzorius = () => {
return;
}
const {
multiSendContract,
linearVotingMasterCopyContract,
linearVotingERC721MasterCopyContract,
fractalAzoriusMasterCopyContract,
Expand All @@ -80,7 +81,6 @@ const useDeployAzorius = () => {
const builderBaseContracts: BaseContracts = {
fractalModuleMasterCopyContract: fractalModuleMasterCopyContract.asProvider,
multisigFreezeGuardMasterCopyContract: multisigFreezeGuardMasterCopyContract.asProvider,
multiSendContract: multiSendContract.asProvider,
freezeERC20VotingMasterCopyContract: freezeERC20VotingMasterCopyContract.asProvider,
freezeERC721VotingMasterCopyContract: freezeERC721VotingMasterCopyContract.asProvider,
freezeMultisigVotingMasterCopyContract: freezeMultisigVotingMasterCopyContract.asProvider,
Expand All @@ -100,6 +100,7 @@ const useDeployAzorius = () => {
safeFactory,
safeSingleton,
zodiacModuleProxyFactory,
multiSendCallOnly,
undefined,
undefined,
);
Expand All @@ -111,21 +112,24 @@ const useDeployAzorius = () => {
owners: safe.owners,
});

if (!isHex(safeTx)) {
throw new Error('Encoded safeTx is not a hex string');
}

const encodedAddOwnerWithThreshold = encodeFunctionData({
abi: GnosisSafeL2Abi,
functionName: 'addOwnerWithThreshold',
args: [getAddress(multiSendContract.asProvider.address), 1n],
args: [multiSendCallOnly, 1n],
});

const encodedMultisend = encodeFunctionData({
abi: MultiSendCallOnlyAbi,
functionName: 'multiSend',
args: [safeTx],
});

const encodedMultisend = multiSendContract.asProvider.interface.encodeFunctionData(
'multiSend',
[safeTx],
);
if (!isHex(encodedMultisend)) {
return;
}
const proposalData: ProposalExecuteData = {
targets: [daoAddress, getAddress(multiSendContract.asProvider.address)],
targets: [daoAddress, multiSendCallOnly],
values: [0n, 0n],
calldatas: [encodedAddOwnerWithThreshold, encodedMultisend],
metaData: {
Expand Down Expand Up @@ -163,6 +167,7 @@ const useDeployAzorius = () => {
safeFactory,
safeSingleton,
zodiacModuleProxyFactory,
multiSendCallOnly,
],
);

Expand Down
Loading

0 comments on commit 800009c

Please sign in to comment.