From 459e40087e39fe2965a7ba79b6e80951d5dc3bb4 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Thu, 23 May 2024 08:03:45 -0400 Subject: [PATCH] Remove more instances of Azorius typechain --- .../ui/menus/ManageDAO/ManageDAOMenu.tsx | 35 ++-- .../ui/proposal/useProposalCountdown.tsx | 2 +- .../loaders/governance/useAzoriusListeners.ts | 195 ++++++++---------- .../loaders/governance/useAzoriusProposals.ts | 77 ++++--- .../governance/useERC20LinearStrategy.ts | 19 +- .../governance/useERC721LinearStrategy.ts | 19 +- .../DAO/loaders/useGovernanceContracts.ts | 12 +- src/hooks/DAO/proposal/useExecuteProposal.ts | 36 ++-- .../DAO/proposal/useUpdateProposalState.ts | 20 +- src/hooks/safe/useSafeContracts.ts | 9 - src/utils/azorius.ts | 43 ++-- 11 files changed, 238 insertions(+), 229 deletions(-) diff --git a/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx b/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx index 2e22d7ac93..e98e185f16 100644 --- a/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx +++ b/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx @@ -3,7 +3,9 @@ import { ERC20FreezeVoting, MultisigFreezeVoting } from '@fractal-framework/frac import { GearFine } from '@phosphor-icons/react'; import { useMemo, useCallback, useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Address, getAddress } from 'viem'; +import { Address, getAddress, getContract } from 'viem'; +import { usePublicClient } from 'wagmi'; +import AzoriusAbi from '../../../../assets/abi/Azorius'; import { SENTINEL_ADDRESS } from '../../../../constants/common'; import { DAO_ROUTES } from '../../../../constants/routes'; import { @@ -68,6 +70,7 @@ export function ManageDAOMenu({ parentAddress, childSafeInfo: fractalNode, }); + const publicClient = usePublicClient(); useEffect(() => { const loadGovernanceType = async () => { @@ -76,23 +79,20 @@ export function ManageDAOMenu({ // are the same - we can simply grab governance type from global scope and avoid double-fetching setGovernanceType(type); } else { - if (baseContracts) { + if (fractalNode?.fractalModules) { let result = GovernanceType.MULTISIG; const azoriusModule = getAzoriusModuleFromModules(fractalNode.fractalModules); - const { fractalAzoriusMasterCopyContract } = baseContracts; - if (!!azoriusModule) { - const azoriusContract = { - asProvider: fractalAzoriusMasterCopyContract.asProvider.attach( - azoriusModule.moduleAddress, - ), - asSigner: fractalAzoriusMasterCopyContract.asSigner.attach( - azoriusModule.moduleAddress, - ), - }; + if (!!azoriusModule && publicClient) { // @dev assumes the first strategy is the voting contract + const azoriusContract = getContract({ + abi: AzoriusAbi, + address: getAddress(azoriusModule.moduleAddress), + client: publicClient, + }); + const votingContractAddress = ( - await azoriusContract.asProvider.getStrategies(SENTINEL_ADDRESS, 0) + await azoriusContract.read.getStrategies([SENTINEL_ADDRESS, 0n]) )[1]; const masterCopyData = await getZodiacModuleProxyMasterCopyData( getAddress(votingContractAddress), @@ -111,7 +111,14 @@ export function ManageDAOMenu({ }; loadGovernanceType(); - }, [fractalNode, safe, safeAddress, type, getZodiacModuleProxyMasterCopyData, baseContracts]); + }, [ + fractalNode?.fractalModules, + getZodiacModuleProxyMasterCopyData, + publicClient, + safe, + safeAddress, + type, + ]); const { addressPrefix } = useNetworkConfig(); const handleNavigateToSettings = useCallback(() => { diff --git a/src/components/ui/proposal/useProposalCountdown.tsx b/src/components/ui/proposal/useProposalCountdown.tsx index 92e85ec5dc..706ee8d308 100644 --- a/src/components/ui/proposal/useProposalCountdown.tsx +++ b/src/components/ui/proposal/useProposalCountdown.tsx @@ -62,7 +62,7 @@ export function useProposalCountdown(proposal: FractalProposal) { (async () => { try { if (dao?.isAzorius) { - await updateProposalState(BigInt(proposal.proposalId)); + await updateProposalState(Number(proposal.proposalId)); } else { await loadDAOProposals(); } diff --git a/src/hooks/DAO/loaders/governance/useAzoriusListeners.ts b/src/hooks/DAO/loaders/governance/useAzoriusListeners.ts index 95afa5b4ea..76b215129d 100644 --- a/src/hooks/DAO/loaders/governance/useAzoriusListeners.ts +++ b/src/hooks/DAO/loaders/governance/useAzoriusListeners.ts @@ -1,97 +1,21 @@ -import { TypedListener } from '@fractal-framework/fractal-contracts/dist/typechain-types/common'; -import { TimelockPeriodUpdatedEvent } from '@fractal-framework/fractal-contracts/dist/typechain-types/contracts/MultisigFreezeGuard'; -import { - Azorius, - ProposalCreatedEvent, -} from '@fractal-framework/fractal-contracts/dist/typechain-types/contracts/azorius/Azorius'; -import { Dispatch, useEffect, useMemo } from 'react'; -import { getAddress, getContract, GetContractReturnType, Hex, PublicClient } from 'viem'; +import { useEffect, useMemo } from 'react'; +import { getAddress, getContract } from 'viem'; import { usePublicClient } from 'wagmi'; +import AzoriusAbi from '../../../../assets/abi/Azorius'; import LinearERC20VotingAbi from '../../../../assets/abi/LinearERC20Voting'; import LinearERC721VotingAbi from '../../../../assets/abi/LinearERC721Voting'; import { useFractal } from '../../../../providers/App/AppProvider'; import { FractalGovernanceAction } from '../../../../providers/App/governance/action'; import { useEthersProvider } from '../../../../providers/Ethers/hooks/useEthersProvider'; -import { - CreateProposalMetadata, - VotingStrategyType, - DecodedTransaction, - FractalActions, -} from '../../../../types'; -import { Providers } from '../../../../types/network'; +import { CreateProposalMetadata, VotingStrategyType } from '../../../../types'; import { getProposalVotesSummary, mapProposalCreatedEventToProposal, decodeTransactions, } from '../../../../utils'; import { getAverageBlockTime } from '../../../../utils/contract'; -import useSafeContracts from '../../../safe/useSafeContracts'; import { useSafeDecoder } from '../../../utils/useSafeDecoder'; -const proposalCreatedEventListener = ( - azoriusContract: Azorius, - erc20StrategyContract: - | GetContractReturnType - | undefined, - erc721StrategyContract: - | GetContractReturnType - | undefined, - provider: Providers, - strategyType: VotingStrategyType, - decode: (value: string, to: string, data?: string | undefined) => Promise, - dispatch: Dispatch, -): TypedListener => { - return async (_strategyAddress, proposalId, proposer, transactions, metadata) => { - // Wait for a block before processing. - // We've seen that calling smart contract functions in `mapProposalCreatedEventToProposal` - // which include the `proposalId` error out because the RPC node (rather, the block it's on) - // doesn't see this proposal yet (despite the event being caught in the app...). - const averageBlockTime = await getAverageBlockTime(provider); - await new Promise(resolve => setTimeout(resolve, averageBlockTime * 1000)); - - if (!metadata) { - return; - } - - const typedTransactions = transactions.map(t => ({ - ...t, - to: getAddress(t.to), - data: t.data as Hex, // @todo - this type casting shouldn't be needed after migrating to getContract - value: t.value.toBigInt(), - })); - - const metaDataEvent: CreateProposalMetadata = JSON.parse(metadata); - const proposalData = { - metaData: { - title: metaDataEvent.title, - description: metaDataEvent.description, - documentationUrl: metaDataEvent.documentationUrl, - }, - transactions: typedTransactions, - decodedTransactions: await decodeTransactions(decode, typedTransactions), - }; - - const proposal = await mapProposalCreatedEventToProposal( - erc20StrategyContract, - erc721StrategyContract, - strategyType, - proposalId.toBigInt(), - proposer, - azoriusContract, - provider, - Promise.resolve(undefined), - Promise.resolve(undefined), - Promise.resolve(undefined), - proposalData, - ); - - dispatch({ - type: FractalGovernanceAction.UPDATE_PROPOSALS_NEW, - payload: proposal, - }); - }; -}; - export const useAzoriusListeners = () => { const { action, @@ -102,19 +26,22 @@ export const useAzoriusListeners = () => { }, } = useFractal(); - const baseContracts = useSafeContracts(); const provider = useEthersProvider(); const decode = useSafeDecoder(); const publicClient = usePublicClient(); const azoriusContract = useMemo(() => { - if (!baseContracts || !azoriusContractAddress) { + if (!publicClient || !azoriusContractAddress) { return; } - return baseContracts.fractalAzoriusMasterCopyContract.asProvider.attach(azoriusContractAddress); - }, [azoriusContractAddress, baseContracts]); + return getContract({ + abi: AzoriusAbi, + address: getAddress(azoriusContractAddress), + client: publicClient, + }); + }, [azoriusContractAddress, publicClient]); const strategyType = useMemo(() => { if (ozLinearVotingContractAddress) { @@ -155,24 +82,71 @@ export const useAzoriusListeners = () => { return; } - const proposalCreatedFilter = azoriusContract.filters.ProposalCreated(); - const listener = proposalCreatedEventListener( - azoriusContract, - erc20StrategyContract, - erc721StrategyContract, - provider, - strategyType, - decode, - action.dispatch, - ); + const unwatch = azoriusContract.watchEvent.ProposalCreated({ + onLogs: async logs => { + for (const log of logs) { + if ( + !log.args.strategy || + !log.args.proposalId || + !log.args.metadata || + !log.args.transactions || + !log.args.proposer + ) { + continue; + } - azoriusContract.on(proposalCreatedFilter, listener); + // Wait for a block before processing. + // We've seen that calling smart contract functions in `mapProposalCreatedEventToProposal` + // which include the `proposalId` error out because the RPC node (rather, the block it's on) + // doesn't see this proposal yet (despite the event being caught in the app...). + const averageBlockTime = await getAverageBlockTime(provider); + await new Promise(resolve => setTimeout(resolve, averageBlockTime * 1000)); + + const typedTransactions = log.args.transactions.map(t => ({ + ...t, + to: t.to, + data: t.data, + value: t.value, + })); + + const metaDataEvent: CreateProposalMetadata = JSON.parse(log.args.metadata); + const proposalData = { + metaData: { + title: metaDataEvent.title, + description: metaDataEvent.description, + documentationUrl: metaDataEvent.documentationUrl, + }, + transactions: typedTransactions, + decodedTransactions: await decodeTransactions(decode, typedTransactions), + }; + + const proposal = await mapProposalCreatedEventToProposal( + erc20StrategyContract, + erc721StrategyContract, + strategyType, + Number(log.args.proposalId), + log.args.proposer, + azoriusContract, + provider, + Promise.resolve(undefined), + Promise.resolve(undefined), + Promise.resolve(undefined), + proposalData, + ); + + action.dispatch({ + type: FractalGovernanceAction.UPDATE_PROPOSALS_NEW, + payload: proposal, + }); + } + }, + }); return () => { - azoriusContract.off(proposalCreatedFilter, listener); + unwatch(); }; }, [ - action.dispatch, + action, azoriusContract, decode, erc20StrategyContract, @@ -197,7 +171,7 @@ export const useAzoriusListeners = () => { erc20StrategyContract, undefined, strategyType, - BigInt(log.args.proposalId), + log.args.proposalId, ); action.dispatch({ @@ -241,7 +215,7 @@ export const useAzoriusListeners = () => { undefined, erc721StrategyContract, strategyType, - BigInt(log.args.proposalId), + log.args.proposalId, ); action.dispatch({ @@ -269,18 +243,23 @@ export const useAzoriusListeners = () => { return; } - const timeLockPeriodFilter = azoriusContract.filters.TimelockPeriodUpdated(); - const timelockPeriodListener: TypedListener = timelockPeriod => { - action.dispatch({ - type: FractalGovernanceAction.UPDATE_TIMELOCK_PERIOD, - payload: BigInt(timelockPeriod), - }); - }; + const unwatch = azoriusContract.watchEvent.TimelockPeriodUpdated({ + onLogs: logs => { + for (const log of logs) { + if (!log.args.timelockPeriod) { + continue; + } - azoriusContract.on(timeLockPeriodFilter, timelockPeriodListener); + action.dispatch({ + type: FractalGovernanceAction.UPDATE_TIMELOCK_PERIOD, + payload: BigInt(log.args.timelockPeriod), + }); + } + }, + }); return () => { - azoriusContract.off(timeLockPeriodFilter, timelockPeriodListener); + unwatch(); }; }, [action, azoriusContract]); }; diff --git a/src/hooks/DAO/loaders/governance/useAzoriusProposals.ts b/src/hooks/DAO/loaders/governance/useAzoriusProposals.ts index 73cec33533..8a0ccc742c 100644 --- a/src/hooks/DAO/loaders/governance/useAzoriusProposals.ts +++ b/src/hooks/DAO/loaders/governance/useAzoriusProposals.ts @@ -1,27 +1,27 @@ -import { - Azorius, - ProposalExecutedEvent, -} from '@fractal-framework/fractal-contracts/dist/typechain-types/contracts/azorius/Azorius'; import { useCallback, useEffect, useMemo, useRef } from 'react'; import { GetContractEventsReturnType, GetContractReturnType, - Hex, PublicClient, getAddress, getContract, } from 'viem'; import { usePublicClient } from 'wagmi'; +import AzoriusAbi from '../../../../assets/abi/Azorius'; import LinearERC20VotingAbi from '../../../../assets/abi/LinearERC20Voting'; import LinearERC721VotingAbi from '../../../../assets/abi/LinearERC721Voting'; import { logError } from '../../../../helpers/errorLogging'; import { useFractal } from '../../../../providers/App/AppProvider'; import { useEthersProvider } from '../../../../providers/Ethers/hooks/useEthersProvider'; -import { CreateProposalMetadata, VotingStrategyType, DecodedTransaction } from '../../../../types'; +import { + CreateProposalMetadata, + VotingStrategyType, + DecodedTransaction, + MetaTransaction, +} from '../../../../types'; import { AzoriusProposal } from '../../../../types/daoProposal'; import { Providers } from '../../../../types/network'; import { mapProposalCreatedEventToProposal, decodeTransactions } from '../../../../utils'; -import useSafeContracts from '../../../safe/useSafeContracts'; import { useSafeDecoder } from '../../../utils/useSafeDecoder'; export const useAzoriusProposals = () => { @@ -35,19 +35,22 @@ export const useAzoriusProposals = () => { }, } = useFractal(); - const baseContracts = useSafeContracts(); const provider = useEthersProvider(); const decode = useSafeDecoder(); const publicClient = usePublicClient(); const azoriusContract = useMemo(() => { - if (!baseContracts || !azoriusContractAddress) { + if (!azoriusContractAddress || !publicClient) { return; } - return baseContracts.fractalAzoriusMasterCopyContract.asProvider.attach(azoriusContractAddress); - }, [azoriusContractAddress, baseContracts]); + return getContract({ + abi: AzoriusAbi, + address: getAddress(azoriusContractAddress), + client: publicClient, + }); + }, [azoriusContractAddress, publicClient]); const strategyType = useMemo(() => { if (ozLinearVotingContractAddress) { @@ -104,9 +107,7 @@ export const useAzoriusProposals = () => { return; } - const filter = azoriusContract.filters.ProposalExecuted(); - const events = await azoriusContract.queryFilter(filter); - + const events = await azoriusContract.getEvents.ProposalExecuted(); return events; }, [azoriusContract]); @@ -122,7 +123,7 @@ export const useAzoriusProposals = () => { const loadAzoriusProposals = useCallback( async ( - _azoriusContract: Azorius | undefined, + _azoriusContract: GetContractReturnType | undefined, _erc20StrategyContract: | GetContractReturnType | undefined, @@ -136,7 +137,9 @@ export const useAzoriusProposals = () => { _erc721VotedEvents: Promise< GetContractEventsReturnType | undefined >, - _executedEvents: Promise, + _executedEvents: Promise< + GetContractEventsReturnType | undefined + >, _provider: Providers | undefined, _decode: ( value: string, @@ -148,11 +151,7 @@ export const useAzoriusProposals = () => { if (!_strategyType || !_azoriusContract || !_provider) { return; } - - const proposalCreatedFilter = _azoriusContract.filters.ProposalCreated(); - const proposalCreatedEvents = ( - await _azoriusContract.queryFilter(proposalCreatedFilter) - ).reverse(); + const proposalCreatedEvents = (await _azoriusContract.getEvents.ProposalCreated()).reverse(); for (const proposalCreatedEvent of proposalCreatedEvents) { let proposalData; @@ -162,29 +161,27 @@ export const useAzoriusProposals = () => { proposalCreatedEvent.args.metadata, ); - const decodedTransactions = await decodeTransactions( - _decode, - proposalCreatedEvent.args.transactions.map(t => ({ - ...t, - to: getAddress(t.to), - // @dev if decodeTransactions worked - we can be certain that this is Hex so type casting should be save. - // Also this will change and this casting won't be needed after migrating to viem's getContract - data: t.data as Hex, - value: t.value.toBigInt(), - })), - ); + let transactions: MetaTransaction[] = []; + let decodedTransactions: DecodedTransaction[] = []; + + if (proposalCreatedEvent.args.transactions) { + transactions = proposalCreatedEvent.args.transactions.map(t => ({ + to: t.to, + data: t.data, + value: t.value, + operation: t.operation, + })); + + decodedTransactions = await decodeTransactions(_decode, transactions); + } + proposalData = { metaData: { title: metadataEvent.title, description: metadataEvent.description, documentationUrl: metadataEvent.documentationUrl, }, - transactions: proposalCreatedEvent.args.transactions.map(t => ({ - ...t, - to: getAddress(t.to), - value: t.value.toBigInt(), - data: t.data as Hex, // @dev Same here - })), + transactions, decodedTransactions, }; } catch { @@ -202,8 +199,8 @@ export const useAzoriusProposals = () => { _erc20StrategyContract, _erc721StrategyContract, _strategyType, - proposalCreatedEvent.args.proposalId.toBigInt(), - proposalCreatedEvent.args.proposer, + Number(proposalCreatedEvent.args.proposalId), + proposalCreatedEvent.args.proposer || '', _azoriusContract, _provider, _erc20VotedEvents, diff --git a/src/hooks/DAO/loaders/governance/useERC20LinearStrategy.ts b/src/hooks/DAO/loaders/governance/useERC20LinearStrategy.ts index 304b3aecfc..dc35218fb4 100644 --- a/src/hooks/DAO/loaders/governance/useERC20LinearStrategy.ts +++ b/src/hooks/DAO/loaders/governance/useERC20LinearStrategy.ts @@ -1,6 +1,7 @@ import { useCallback, useEffect, useMemo } from 'react'; import { getAddress, getContract } from 'viem'; import { usePublicClient } from 'wagmi'; +import AzoriusAbi from '../../../../assets/abi/Azorius'; import LinearERC20VotingAbi from '../../../../assets/abi/LinearERC20Voting'; import { useFractal } from '../../../../providers/App/AppProvider'; import { FractalGovernanceAction } from '../../../../providers/App/governance/action'; @@ -33,18 +34,27 @@ export const useERC20LinearStrategy = () => { }, [ozLinearVotingContractAddress, publicClient]); const loadERC20Strategy = useCallback(async () => { - if (!ozLinearVotingContract || !azoriusContractAddress || !provider || !baseContracts) { + if ( + !ozLinearVotingContract || + !azoriusContractAddress || + !provider || + !baseContracts || + !publicClient + ) { return {}; } - const azoriusContract = - baseContracts.fractalAzoriusMasterCopyContract.asProvider.attach(azoriusContractAddress); + const azoriusContract = getContract({ + abi: AzoriusAbi, + address: getAddress(azoriusContractAddress), + client: publicClient, + }); const [votingPeriodBlocks, quorumNumerator, quorumDenominator, timeLockPeriod] = await Promise.all([ ozLinearVotingContract.read.votingPeriod(), ozLinearVotingContract.read.quorumNumerator(), ozLinearVotingContract.read.QUORUM_DENOMINATOR(), - azoriusContract.timelockPeriod(), + azoriusContract.read.timelockPeriod(), ]); const quorumPercentage = (quorumNumerator * 100n) / quorumDenominator; @@ -73,6 +83,7 @@ export const useERC20LinearStrategy = () => { getTimeDuration, ozLinearVotingContract, provider, + publicClient, ]); useEffect(() => { diff --git a/src/hooks/DAO/loaders/governance/useERC721LinearStrategy.ts b/src/hooks/DAO/loaders/governance/useERC721LinearStrategy.ts index ce478e6b31..778a5e2ab1 100644 --- a/src/hooks/DAO/loaders/governance/useERC721LinearStrategy.ts +++ b/src/hooks/DAO/loaders/governance/useERC721LinearStrategy.ts @@ -1,6 +1,7 @@ import { useCallback, useEffect, useMemo } from 'react'; import { getAddress, getContract } from 'viem'; import { usePublicClient } from 'wagmi'; +import AzoriusAbi from '../../../../assets/abi/Azorius'; import LinearERC721VotingAbi from '../../../../assets/abi/LinearERC721Voting'; import { useFractal } from '../../../../providers/App/AppProvider'; import { FractalGovernanceAction } from '../../../../providers/App/governance/action'; @@ -33,17 +34,26 @@ export const useERC721LinearStrategy = () => { }, [erc721LinearVotingContractAddress, publicClient]); const loadERC721Strategy = useCallback(async () => { - if (!azoriusContractAddress || !provider || !baseContracts || !erc721LinearVotingContract) { + if ( + !azoriusContractAddress || + !provider || + !baseContracts || + !erc721LinearVotingContract || + !publicClient + ) { return {}; } - const azoriusContract = - baseContracts.fractalAzoriusMasterCopyContract.asProvider.attach(azoriusContractAddress); + const azoriusContract = getContract({ + abi: AzoriusAbi, + address: getAddress(azoriusContractAddress), + client: publicClient, + }); const [votingPeriodBlocks, quorumThreshold, timeLockPeriod] = await Promise.all([ erc721LinearVotingContract.read.votingPeriod(), erc721LinearVotingContract.read.quorumThreshold(), - azoriusContract.timelockPeriod(), + azoriusContract.read.timelockPeriod(), ]); const votingPeriodValue = await blocksToSeconds(votingPeriodBlocks, provider); @@ -71,6 +81,7 @@ export const useERC721LinearStrategy = () => { erc721LinearVotingContract, getTimeDuration, provider, + publicClient, ]); useEffect(() => { diff --git a/src/hooks/DAO/loaders/useGovernanceContracts.ts b/src/hooks/DAO/loaders/useGovernanceContracts.ts index 1ed8d83a61..589b9ffc1c 100644 --- a/src/hooks/DAO/loaders/useGovernanceContracts.ts +++ b/src/hooks/DAO/loaders/useGovernanceContracts.ts @@ -26,7 +26,6 @@ export const useGovernanceContracts = () => { if (!baseContracts || !publicClient) { return; } - const { fractalAzoriusMasterCopyContract } = baseContracts; const azoriusModule = getAzoriusModuleFromModules(fractalModules); if (!azoriusModule) { @@ -37,15 +36,12 @@ export const useGovernanceContracts = () => { return; } - const azoriusModuleContract = getContract({ + const azoriusContract = getContract({ abi: AzoriusAbi, address: getAddress(azoriusModule.moduleAddress), client: publicClient, }); - const azoriusContract = fractalAzoriusMasterCopyContract.asProvider.attach( - azoriusModuleContract.address, - ); let ozLinearVotingContractAddress: string | undefined; let erc721LinearVotingContractAddress: string | undefined; let votesTokenContractAddress: string | undefined; @@ -53,7 +49,9 @@ export const useGovernanceContracts = () => { let lockReleaseContractAddress: string | undefined; // @dev assumes the first strategy is the voting contract - const votingStrategyAddress = (await azoriusContract.getStrategies(SENTINEL_ADDRESS, 0))[1]; + const votingStrategyAddress = ( + await azoriusContract.read.getStrategies([SENTINEL_ADDRESS, 0n]) + )[1]; const masterCopyData = await getZodiacModuleProxyMasterCopyData( getAddress(votingStrategyAddress), @@ -116,7 +114,7 @@ export const useGovernanceContracts = () => { payload: { ozLinearVotingContractAddress, erc721LinearVotingContractAddress, - azoriusContractAddress: azoriusModuleContract.address, + azoriusContractAddress: azoriusModule.moduleAddress, votesTokenContractAddress, underlyingTokenAddress, lockReleaseContractAddress, diff --git a/src/hooks/DAO/proposal/useExecuteProposal.ts b/src/hooks/DAO/proposal/useExecuteProposal.ts index 9b5cbd09fc..fc9b8a8e17 100644 --- a/src/hooks/DAO/proposal/useExecuteProposal.ts +++ b/src/hooks/DAO/proposal/useExecuteProposal.ts @@ -1,8 +1,10 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { Address, Hex, getAddress, getContract } from 'viem'; +import { useWalletClient } from 'wagmi'; +import AzoriusAbi from '../../../assets/abi/Azorius'; import { useFractal } from '../../../providers/App/AppProvider'; import { MetaTransaction, FractalProposal, AzoriusProposal } from '../../../types'; -import useSafeContracts from '../../safe/useSafeContracts'; import { useTransaction } from '../../utils/useTransaction'; import useUpdateProposalState from './useUpdateProposalState'; @@ -11,12 +13,12 @@ export default function useExecuteProposal() { const { governanceContracts, action } = useFractal(); const { azoriusContractAddress } = governanceContracts; - const baseContracts = useSafeContracts(); const updateProposalState = useUpdateProposalState({ governanceContracts, governanceDispatch: action.dispatch, }); - const [contractCallExecuteProposal, contractCallPending] = useTransaction(); + const { data: walletClient } = useWalletClient(); + const [, contractCallPending, contractCallViem] = useTransaction(); const executeProposal = useCallback( (proposal: FractalProposal) => { @@ -25,16 +27,20 @@ export default function useExecuteProposal() { !azoriusContractAddress || !azoriusProposal.data || !azoriusProposal.data.transactions || - !baseContracts + !walletClient ) { return; } - const azoriusContract = - baseContracts.fractalAzoriusMasterCopyContract.asSigner.attach(azoriusContractAddress); - const targets: string[] = []; + const azoriusContract = getContract({ + abi: AzoriusAbi, + address: getAddress(azoriusContractAddress), + client: walletClient, + }); + + const targets: Address[] = []; const values: MetaTransaction['value'][] = []; - const data: string[] = []; + const data: Hex[] = []; const operations: number[] = []; azoriusProposal.data.transactions.forEach(tx => { @@ -44,19 +50,25 @@ export default function useExecuteProposal() { operations.push(tx.operation); }); - contractCallExecuteProposal({ + contractCallViem({ contractFn: () => - azoriusContract.executeProposal(proposal.proposalId, targets, values, data, operations), + azoriusContract.write.executeProposal([ + Number(proposal.proposalId), + targets, + values, + data, + operations, + ]), pendingMessage: t('pendingExecute'), failedMessage: t('failedExecute'), successMessage: t('successExecute'), successCallback: async () => { // @todo may need to re-add a loader here - updateProposalState(BigInt(proposal.proposalId)); + updateProposalState(Number(proposal.proposalId)); }, }); }, - [contractCallExecuteProposal, t, azoriusContractAddress, updateProposalState, baseContracts], + [azoriusContractAddress, contractCallViem, t, updateProposalState, walletClient], ); return { diff --git a/src/hooks/DAO/proposal/useUpdateProposalState.ts b/src/hooks/DAO/proposal/useUpdateProposalState.ts index dd7535bfc5..edc3140bd9 100644 --- a/src/hooks/DAO/proposal/useUpdateProposalState.ts +++ b/src/hooks/DAO/proposal/useUpdateProposalState.ts @@ -1,11 +1,13 @@ import { useCallback, Dispatch } from 'react'; +import { getAddress, getContract } from 'viem'; +import { usePublicClient } from 'wagmi'; +import AzoriusAbi from '../../../assets/abi/Azorius'; import { FractalGovernanceAction, FractalGovernanceActions, } from '../../../providers/App/governance/action'; import { FractalGovernanceContracts } from '../../../types'; import { getAzoriusProposalState } from '../../../utils'; -import useSafeContracts from '../../safe/useSafeContracts'; interface IUseUpdateProposalState { governanceContracts: FractalGovernanceContracts; @@ -16,21 +18,25 @@ export default function useUpdateProposalState({ governanceContracts: { azoriusContractAddress }, governanceDispatch, }: IUseUpdateProposalState) { - const baseContracts = useSafeContracts(); + const publicClient = usePublicClient(); const updateProposalState = useCallback( - async (proposalId: bigint) => { - if (!azoriusContractAddress || !baseContracts) { + async (proposalId: number) => { + if (!azoriusContractAddress || !publicClient) { return; } - const azoriusContract = - baseContracts.fractalAzoriusMasterCopyContract.asProvider.attach(azoriusContractAddress); + const azoriusContract = getContract({ + abi: AzoriusAbi, + address: getAddress(azoriusContractAddress), + client: publicClient, + }); + const newState = await getAzoriusProposalState(azoriusContract, proposalId); governanceDispatch({ type: FractalGovernanceAction.UPDATE_PROPOSAL_STATE, payload: { proposalId: proposalId.toString(), state: newState }, }); }, - [azoriusContractAddress, governanceDispatch, baseContracts], + [azoriusContractAddress, governanceDispatch, publicClient], ); return updateProposalState; diff --git a/src/hooks/safe/useSafeContracts.ts b/src/hooks/safe/useSafeContracts.ts index a906cebc61..a0857c34b3 100644 --- a/src/hooks/safe/useSafeContracts.ts +++ b/src/hooks/safe/useSafeContracts.ts @@ -3,7 +3,6 @@ import { ERC20FreezeVoting__factory, MultisigFreezeGuard__factory, MultisigFreezeVoting__factory, - Azorius__factory, ERC721FreezeVoting__factory, } from '@fractal-framework/fractal-contracts'; import { useMemo } from 'react'; @@ -17,7 +16,6 @@ export default function useSafeContracts() { const { contracts: { - fractalAzoriusMasterCopy, multisigFreezeGuardMasterCopy, azoriusFreezeGuardMasterCopy, multisigFreezeVotingMasterCopy, @@ -31,11 +29,6 @@ export default function useSafeContracts() { return; } - const fractalAzoriusMasterCopyContract = { - asSigner: Azorius__factory.connect(fractalAzoriusMasterCopy, signerOrProvider), - asProvider: Azorius__factory.connect(fractalAzoriusMasterCopy, provider), - }; - const multisigFreezeGuardMasterCopyContract = { asSigner: MultisigFreezeGuard__factory.connect( multisigFreezeGuardMasterCopy, @@ -68,7 +61,6 @@ export default function useSafeContracts() { }; return { - fractalAzoriusMasterCopyContract, multisigFreezeGuardMasterCopyContract, azoriusFreezeGuardMasterCopyContract, freezeMultisigVotingMasterCopyContract, @@ -76,7 +68,6 @@ export default function useSafeContracts() { freezeERC721VotingMasterCopyContract, }; }, [ - fractalAzoriusMasterCopy, multisigFreezeGuardMasterCopy, azoriusFreezeGuardMasterCopy, multisigFreezeVotingMasterCopy, diff --git a/src/utils/azorius.ts b/src/utils/azorius.ts index 86d58a8126..e34e54b2f6 100644 --- a/src/utils/azorius.ts +++ b/src/utils/azorius.ts @@ -1,7 +1,6 @@ -import { Azorius } from '@fractal-framework/fractal-contracts'; -import { ProposalExecutedEvent } from '@fractal-framework/fractal-contracts/dist/typechain-types/contracts/azorius/Azorius'; import { SafeMultisigTransactionWithTransfersResponse } from '@safe-global/safe-service-client'; import { GetContractEventsReturnType, GetContractReturnType, PublicClient } from 'viem'; +import AzoriusAbi from '../assets/abi/Azorius'; import LinearERC20VotingAbi from '../assets/abi/LinearERC20Voting'; import LinearERC721VotingAbi from '../assets/abi/LinearERC721Voting'; import { strategyFractalProposalStates } from '../constants/strategy'; @@ -28,10 +27,10 @@ import { Providers } from '../types/network'; import { getTimeStamp } from './contract'; export const getAzoriusProposalState = async ( - azoriusContract: Azorius, - proposalId: bigint, + azoriusContract: GetContractReturnType, + proposalId: number, ): Promise => { - const state = await azoriusContract.proposalState(proposalId); + const state = await azoriusContract.read.proposalState([proposalId]); return strategyFractalProposalStates[state]; }; @@ -43,12 +42,12 @@ const getQuorum = async ( | GetContractReturnType | undefined, strategyType: VotingStrategyType, - proposalId: bigint, + proposalId: number, ) => { let quorum; if (strategyType === VotingStrategyType.LINEAR_ERC20 && erc20StrategyContract) { - quorum = await erc20StrategyContract.read.quorumVotes([Number(proposalId)]); + quorum = await erc20StrategyContract.read.quorumVotes([proposalId]); } else if (strategyType === VotingStrategyType.LINEAR_ERC721 && erc721StrategyContract) { quorum = await erc721StrategyContract.read.quorumThreshold(); } else { @@ -62,7 +61,7 @@ export const getProposalVotesSummary = async ( erc20Strategy: GetContractReturnType | undefined, erc721Strategy: GetContractReturnType | undefined, strategyType: VotingStrategyType, - proposalId: bigint, + proposalId: number, ): Promise => { try { if (erc20Strategy !== undefined && erc721Strategy !== undefined) { @@ -71,7 +70,7 @@ export const getProposalVotesSummary = async ( if (erc20Strategy !== undefined) { const [noVotes, yesVotes, abstainVotes] = await erc20Strategy.read.getProposalVotes([ - Number(proposalId), + proposalId, ]); return { @@ -82,7 +81,7 @@ export const getProposalVotesSummary = async ( }; } else if (erc721Strategy !== undefined) { const [noVotes, yesVotes, abstainVotes] = await erc721Strategy.read.getProposalVotes([ - Number(proposalId), + proposalId, ]); return { @@ -115,7 +114,7 @@ export const getProposalVotesSummary = async ( const getProposalVotes = ( erc20VotedEvents: GetContractEventsReturnType | undefined, erc721VotedEvents: GetContractEventsReturnType | undefined, - proposalId: bigint, + proposalId: number, ): (ProposalVote | ERC721ProposalVote)[] => { if (erc20VotedEvents !== undefined && erc721VotedEvents !== undefined) { throw new Error("two voting contracts? we don't support that."); @@ -124,7 +123,7 @@ const getProposalVotes = ( if (erc20VotedEvents !== undefined) { const erc20ProposalVoteEvents = erc20VotedEvents.filter(voteEvent => { if (!voteEvent.args.proposalId) return false; - return proposalId === BigInt(voteEvent.args.proposalId); + return proposalId === voteEvent.args.proposalId; }); const events = []; @@ -142,7 +141,7 @@ const getProposalVotes = ( } else if (erc721VotedEvents !== undefined) { const erc721ProposalVoteEvents = erc721VotedEvents.filter(voteEvent => { if (!voteEvent.args.proposalId) return false; - return proposalId === BigInt(voteEvent.args.proposalId); + return proposalId === voteEvent.args.proposalId; }); const events = []; @@ -171,9 +170,9 @@ export const mapProposalCreatedEventToProposal = async ( | GetContractReturnType | undefined, strategyType: VotingStrategyType, - proposalId: bigint, + proposalId: number, proposer: string, - azoriusContract: Azorius, + azoriusContract: GetContractReturnType, provider: Providers, erc20VotedEvents: Promise< GetContractEventsReturnType | undefined @@ -181,7 +180,9 @@ export const mapProposalCreatedEventToProposal = async ( erc721VotedEvents: Promise< GetContractEventsReturnType | undefined >, - executedEvents: Promise, + executedEvents: Promise< + GetContractEventsReturnType | undefined + >, data?: ProposalData, ) => { if (erc20StrategyContract !== undefined && erc721StrategyContract !== undefined) { @@ -197,18 +198,14 @@ export const mapProposalCreatedEventToProposal = async ( }; if (erc20StrategyContract !== undefined) { - const stratProposalVotes = await erc20StrategyContract.read.getProposalVotes([ - Number(proposalId), - ]); + const stratProposalVotes = await erc20StrategyContract.read.getProposalVotes([proposalId]); proposalVotes.noVotes = stratProposalVotes[0]; proposalVotes.yesVotes = stratProposalVotes[1]; proposalVotes.abstainVotes = stratProposalVotes[2]; proposalVotes.startBlock = stratProposalVotes[3]; proposalVotes.endBlock = stratProposalVotes[4]; } else if (erc721StrategyContract !== undefined) { - const stratProposalVotes = await erc721StrategyContract.read.getProposalVotes([ - Number(proposalId), - ]); + const stratProposalVotes = await erc721StrategyContract.read.getProposalVotes([proposalId]); proposalVotes.noVotes = stratProposalVotes[0]; proposalVotes.yesVotes = stratProposalVotes[1]; proposalVotes.abstainVotes = stratProposalVotes[2]; @@ -243,7 +240,7 @@ export const mapProposalCreatedEventToProposal = async ( let transactionHash: string | undefined; if (state === FractalProposalState.EXECUTED) { const executedEvent = (await executedEvents)?.find( - event => BigInt(event.args[0]) === proposalId, + event => event.args.proposalId === proposalId, ); transactionHash = executedEvent?.transactionHash; }