feat: quick fix for new governor

This commit is contained in:
Noah Zinsmeister 2021-06-13 15:15:00 -04:00
parent 9eb20624cb
commit 5dd1249ddd
No known key found for this signature in database
GPG Key ID: 83022DD49188C9F2
6 changed files with 122 additions and 104 deletions

@ -16,10 +16,12 @@ export const V2_ROUTER_ADDRESS: AddressMap = constructSameAddressMap(
'0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
false false
) )
export const GOVERNANCE_ADDRESS: AddressMap = constructSameAddressMap( export const GOVERNANCE_ADDRESSES: AddressMap[] = [
'0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F', constructSameAddressMap('0x5e4be8Bc9637f0EAA1A755019e06A68ce081D58F', false),
false {
) [SupportedChainId.MAINNET]: '0xC4e172459f1E7939D522503B81AFAaC1014CE6F6',
},
]
export const TIMELOCK_ADDRESS: AddressMap = constructSameAddressMap('0x1a9C8182C09F50C8318d769245beA52c32BE35BC', false) export const TIMELOCK_ADDRESS: AddressMap = constructSameAddressMap('0x1a9C8182C09F50C8318d769245beA52c32BE35BC', false)
export const MERKLE_DISTRIBUTOR_ADDRESS: AddressMap = { export const MERKLE_DISTRIBUTOR_ADDRESS: AddressMap = {
[SupportedChainId.MAINNET]: '0x090D4613473dEE047c3f2706764f49E0821D256e', [SupportedChainId.MAINNET]: '0x090D4613473dEE047c3f2706764f49E0821D256e',

@ -1,31 +1,12 @@
import { GOVERNANCE_ADDRESS, TIMELOCK_ADDRESS, UNI_ADDRESS } from './addresses' import { GOVERNANCE_ADDRESSES, TIMELOCK_ADDRESS, UNI_ADDRESS } from './addresses'
export const COMMON_CONTRACT_NAMES: { [chainId: number]: { [address: string]: string } } = { export const COMMON_CONTRACT_NAMES: { [chainId: number]: { [address: string]: string } } = {
[1]: { [1]: {
[UNI_ADDRESS[1]]: 'UNI', [UNI_ADDRESS[1]]: 'UNI',
[GOVERNANCE_ADDRESS[1]]: 'Governance', [GOVERNANCE_ADDRESSES[0][1]]: 'Governance (V0)',
[GOVERNANCE_ADDRESSES[1][1]]: 'Governance',
[TIMELOCK_ADDRESS[1]]: 'Timelock', [TIMELOCK_ADDRESS[1]]: 'Timelock',
}, },
[4]: {
[UNI_ADDRESS[4]]: 'Rinkeby UNI',
[GOVERNANCE_ADDRESS[4]]: 'Rinkeby Governance',
[TIMELOCK_ADDRESS[4]]: 'Rinkeby Timelock',
},
[3]: {
[UNI_ADDRESS[3]]: 'Ropsten UNI',
[GOVERNANCE_ADDRESS[3]]: 'Ropsten Governance',
[TIMELOCK_ADDRESS[3]]: 'Ropsten Timelock',
},
[42]: {
[UNI_ADDRESS[42]]: 'Kovan UNI',
[GOVERNANCE_ADDRESS[42]]: 'Kovan Governance',
[TIMELOCK_ADDRESS[42]]: 'Kovan Timelock',
},
[5]: {
[UNI_ADDRESS[5]]: 'Goerli UNI',
[GOVERNANCE_ADDRESS[5]]: 'Goerli Governance',
[TIMELOCK_ADDRESS[5]]: 'Goerli Timelock',
},
} }
export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13 export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13

@ -1,6 +0,0 @@
import { UNISWAP_GRANTS_PROPOSAL_DESCRIPTION } from './uniswap_grants_proposal_description'
// Proposals are 0-indexed
export const PROPOSAL_DESCRIPTION_TEXT: { [proposalId: number]: string } = {
[2]: UNISWAP_GRANTS_PROPOSAL_DESCRIPTION,
}

@ -27,7 +27,7 @@ import {
V3_CORE_FACTORY_ADDRESSES, V3_CORE_FACTORY_ADDRESSES,
V3_MIGRATOR_ADDRESSES, V3_MIGRATOR_ADDRESSES,
ARGENT_WALLET_DETECTOR_ADDRESS, ARGENT_WALLET_DETECTOR_ADDRESS,
GOVERNANCE_ADDRESS, GOVERNANCE_ADDRESSES,
MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ADDRESS,
MULTICALL2_ADDRESSES, MULTICALL2_ADDRESSES,
V2_ROUTER_ADDRESS, V2_ROUTER_ADDRESS,
@ -116,8 +116,11 @@ export function useMerkleDistributorContract() {
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true) return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
} }
export function useGovernanceContract() { export function useGovernanceContracts(): (Contract | null)[] {
return useContract(GOVERNANCE_ADDRESS, GOVERNANCE_ABI, true) return [
useContract(GOVERNANCE_ADDRESSES[0], GOVERNANCE_ABI, false),
useContract(GOVERNANCE_ADDRESSES[1], GOVERNANCE_ABI, true),
]
} }
export function useUniContract() { export function useUniContract() {

@ -120,7 +120,8 @@ export default function Vote() {
const toggleDelegateModal = useToggleDelegateModal() const toggleDelegateModal = useToggleDelegateModal()
// get data to list all proposals // get data to list all proposals
const allProposals: ProposalData[] = useAllProposalData() // TODO don't hardcode for first gov alpha
const allProposals: ProposalData[] = useAllProposalData()[0]
// user data // user data
const availableVotes: CurrencyAmount<Token> | undefined = useUserVotes() const availableVotes: CurrencyAmount<Token> | undefined = useUserVotes()
@ -248,7 +249,7 @@ export default function Vote() {
</TYPE.subHeader> </TYPE.subHeader>
</EmptyProposals> </EmptyProposals>
)} )}
{allProposals?.map((p: ProposalData, i) => { {allProposals?.reverse()?.map((p: ProposalData, i) => {
return ( return (
<Proposal as={Link} to={'/vote/' + p.id} key={i}> <Proposal as={Link} to={'/vote/' + p.id} key={i}>
<ProposalNumber>{p.id}</ProposalNumber> <ProposalNumber>{p.id}</ProposalNumber>

@ -1,8 +1,7 @@
import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { isAddress } from 'ethers/lib/utils' import { isAddress } from 'ethers/lib/utils'
import { PROPOSAL_DESCRIPTION_TEXT } from '../../constants/proposals'
import { UNI } from '../../constants/tokens' import { UNI } from '../../constants/tokens'
import { useGovernanceContract, useUniContract } from '../../hooks/useContract' import { useGovernanceContracts, useUniContract } from '../../hooks/useContract'
import { calculateGasMargin } from '../../utils/calculateGasMargin' import { calculateGasMargin } from '../../utils/calculateGasMargin'
import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks' import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks'
import { useActiveWeb3React } from '../../hooks/web3' import { useActiveWeb3React } from '../../hooks/web3'
@ -11,6 +10,7 @@ import { TransactionResponse } from '@ethersproject/providers'
import { useTransactionAdder } from '../transactions/hooks' import { useTransactionAdder } from '../transactions/hooks'
import { useState, useEffect, useCallback, useMemo } from 'react' import { useState, useEffect, useCallback, useMemo } from 'react'
import { abi as GOV_ABI } from '@uniswap/governance/build/GovernorAlpha.json' import { abi as GOV_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
import { UNISWAP_GRANTS_PROPOSAL_DESCRIPTION } from 'constants/proposals/uniswap_grants_proposal_description'
interface ProposalDetail { interface ProposalDetail {
target: string target: string
@ -43,10 +43,9 @@ export enum ProposalState {
Executed, Executed,
} }
// get count of all proposals made // get count of all proposals made on the given governor alpha
export function useProposalCount(): number | undefined { function useProposalCount(govContract: ethers.Contract | null): number | undefined {
const gov = useGovernanceContract() const res = useSingleCallResult(govContract, 'proposalCount')
const res = useSingleCallResult(gov, 'proposalCount')
if (res.result && !res.loading) { if (res.result && !res.loading) {
return parseInt(res.result[0]) return parseInt(res.result[0])
} }
@ -58,15 +57,15 @@ export function useProposalCount(): number | undefined {
* new proposal event. * new proposal event.
*/ */
const eventParser = new ethers.utils.Interface(GOV_ABI) const eventParser = new ethers.utils.Interface(GOV_ABI)
export function useDataFromEventLogs() { function useDataFromEventLogs(govContract: ethers.Contract | null) {
const { library, chainId } = useActiveWeb3React() const { library, chainId } = useActiveWeb3React()
const [formattedEvents, setFormattedEvents] = const [formattedEvents, setFormattedEvents] =
useState<{ description: string; details: { target: string; functionSig: string; callData: string }[] }[]>() useState<{ description: string; details: { target: string; functionSig: string; callData: string }[] }[]>()
const govContract = useGovernanceContract()
// create filter for these specific events // create filter for these specific events
const filter = useMemo( const filter = useMemo(
() => (govContract ? { ...govContract.filters.ProposalCreated(), fromBlock: 0, toBlock: 'latest' } : undefined), () =>
govContract ? { ...govContract.filters.ProposalCreated(), fromBlock: 10861678, toBlock: 'latest' } : undefined,
[govContract] [govContract]
) )
@ -79,9 +78,7 @@ export function useDataFromEventLogs() {
.getLogs(filter) .getLogs(filter)
.then((proposalEvents) => { .then((proposalEvents) => {
if (stale) return if (stale) return
// reverse events to get them from newest to odlest const formattedEventData = proposalEvents?.map((event) => {
const formattedEventData = proposalEvents
?.map((event) => {
const eventParsed = eventParser.parseLog(event).args const eventParsed = eventParser.parseLog(event).args
return { return {
description: eventParsed.description, description: eventParsed.description,
@ -100,7 +97,6 @@ export function useDataFromEventLogs() {
}), }),
} }
}) })
.reverse()
setFormattedEvents(formattedEventData) setFormattedEvents(formattedEventData)
}) })
.catch((error) => { .catch((error) => {
@ -118,55 +114,93 @@ export function useDataFromEventLogs() {
} }
// get data for all past and active proposals // get data for all past and active proposals
export function useAllProposalData() { export function useAllProposalData(): ProposalData[][] {
const proposalCount = useProposalCount() // fetch all governance contracts
const govContract = useGovernanceContract() const govContracts = useGovernanceContracts()
const proposalIndexes = [] // fetch the proposal count on the active contract
for (let i = 1; i <= (proposalCount ?? 0); i++) { const proposalCount = useProposalCount(govContracts[govContracts.length - 1])
proposalIndexes.push([i])
}
// get metadata from past events // get all proposals for all contracts
const formattedEvents = useDataFromEventLogs() const proposalsIndicesByGovContract = [
[1, 2, 3, 4], // hardcoded for first governor alpha
typeof proposalCount === 'number' ? new Array(proposalCount).fill(0).map((_, i) => i + 1) : [], // dynamic for current governor alpha
]
// get all proposal entities // get all proposal entities
const allProposals = useSingleContractMultipleData(govContract, 'proposals', proposalIndexes) const allProposalsByGovContract = [
useSingleContractMultipleData(
govContracts[0],
'proposals',
proposalsIndicesByGovContract[0].map((i) => [i])
),
useSingleContractMultipleData(
govContracts[1],
'proposals',
proposalsIndicesByGovContract[1].map((i) => [i])
),
]
// get all proposal states // get all proposal states
const allProposalStates = useSingleContractMultipleData(govContract, 'state', proposalIndexes) const allProposalStatesByGovContract = [
useSingleContractMultipleData(
govContracts[0],
'state',
proposalsIndicesByGovContract[0].map((i) => [i])
),
useSingleContractMultipleData(
govContracts[1],
'state',
proposalsIndicesByGovContract[1].map((i) => [i])
),
]
if (formattedEvents && allProposals && allProposalStates) { // get metadata from past events
allProposals.reverse() const formattedEventsByGovContract = [useDataFromEventLogs(govContracts[0]), useDataFromEventLogs(govContracts[1])]
allProposalStates.reverse()
return allProposals const returnData: ProposalData[][] = []
.filter((p, i) => {
return Boolean(p.result) && Boolean(allProposalStates[i]?.result) && Boolean(formattedEvents[i]) for (let governorIndex = 0; governorIndex < allProposalsByGovContract.length; governorIndex++) {
}) const allProposals = allProposalsByGovContract[governorIndex]
.map((p, i) => { const allProposalStates = allProposalStatesByGovContract[governorIndex]
const description = PROPOSAL_DESCRIPTION_TEXT[allProposals.length - i - 1] || formattedEvents[i].description const formattedEvents = formattedEventsByGovContract[governorIndex]
const formattedProposal: ProposalData = {
id: allProposals[i]?.result?.id.toString(), if (
title: description?.split(/# |\n/g)[1] || 'Untitled', allProposals?.every((p) => Boolean(p.result)) &&
description: description || 'No description.', allProposalStates?.every((p) => Boolean(p.result)) &&
proposer: allProposals[i]?.result?.proposer, formattedEvents?.every((p) => Boolean(p))
) {
returnData.push(
allProposals.map((proposal, i): ProposalData => {
let description = formattedEvents[i].description
// overwrite broken description
if (governorIndex === 0 && i === 2) description = UNISWAP_GRANTS_PROPOSAL_DESCRIPTION
return {
id: proposal?.result?.id.toString(),
title: description?.split(/# |\n/g)[1] ?? 'Untitled',
description: description ?? 'No description.',
proposer: proposal?.result?.proposer,
status: allProposalStates[i]?.result?.[0] ?? ProposalState.Undetermined, status: allProposalStates[i]?.result?.[0] ?? ProposalState.Undetermined,
forCount: parseFloat(ethers.utils.formatUnits(allProposals[i]?.result?.forVotes.toString(), 18)), forCount: parseFloat(ethers.utils.formatUnits(proposal?.result?.forVotes.toString(), 18)),
againstCount: parseFloat(ethers.utils.formatUnits(allProposals[i]?.result?.againstVotes.toString(), 18)), againstCount: parseFloat(ethers.utils.formatUnits(proposal?.result?.againstVotes.toString(), 18)),
startBlock: parseInt(allProposals[i]?.result?.startBlock?.toString()), startBlock: parseInt(proposal?.result?.startBlock?.toString()),
endBlock: parseInt(allProposals[i]?.result?.endBlock?.toString()), endBlock: parseInt(proposal?.result?.endBlock?.toString()),
details: formattedEvents[i].details, details: formattedEvents[i].details,
} }
return formattedProposal
}) })
)
} else { } else {
return [] returnData.push([])
} }
}
return returnData
} }
export function useProposalData(id: string): ProposalData | undefined { export function useProposalData(id: string): ProposalData | undefined {
const allProposalData = useAllProposalData() // TODO don't hardcode for first gov alpha
const allProposalData = useAllProposalData()[0]
return allProposalData?.find((p) => p.id === id) return allProposalData?.find((p) => p.id === id)
} }
@ -232,7 +266,10 @@ export function useVoteCallback(): {
} { } {
const { account } = useActiveWeb3React() const { account } = useActiveWeb3React()
const govContract = useGovernanceContract() // we only care about voting on the active governance contract
const govContracts = useGovernanceContracts()
const govContract = govContracts[govContracts.length - 1]
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const voteCallback = useCallback( const voteCallback = useCallback(