From e1c0e47235e9b661dbe9efde54a9f7840966776f Mon Sep 17 00:00:00 2001 From: eladmallel Date: Tue, 9 Jan 2024 16:13:05 -0500 Subject: [PATCH] subgraph: index vote client ID --- .../NounsDAOLogicV3.sol/NounsDAOLogicV3.json | 970 +++++++++++------- .../governance/NounsDAOInterfaces.sol | 5 + .../contracts/governance/NounsDAOV3Votes.sol | 1 + packages/nouns-subgraph/schema.graphql | 3 + .../src/custom-types/ParsedProposalV3.ts | 4 +- packages/nouns-subgraph/src/nouns-dao.ts | 23 +- .../nouns-subgraph/subgraph.yaml.mustache | 2 + 7 files changed, 615 insertions(+), 393 deletions(-) diff --git a/packages/nouns-contracts/abi/contracts/governance/NounsDAOLogicV3.sol/NounsDAOLogicV3.json b/packages/nouns-contracts/abi/contracts/governance/NounsDAOLogicV3.sol/NounsDAOLogicV3.json index d38c979b32..ef159ea7e5 100644 --- a/packages/nouns-contracts/abi/contracts/governance/NounsDAOLogicV3.sol/NounsDAOLogicV3.json +++ b/packages/nouns-contracts/abi/contracts/governance/NounsDAOLogicV3.sol/NounsDAOLogicV3.json @@ -44,6 +44,30 @@ "name": "UnsafeUint16Cast", "type": "error" }, + { + "inputs": [], + "name": "VotesBelowProposalThreshold", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "numTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "DAONounsSupplyIncreasedFromEscrow", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -495,6 +519,80 @@ "name": "ProposalCreated", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ProposalCreatedOnTimelockV1", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -508,6 +606,79 @@ "name": "ProposalCreatedOnTimelockV1", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proposalThreshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "quorumVotes", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "name": "ProposalCreatedWithRequirements", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -608,6 +779,12 @@ "name": "proposer", "type": "address" }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, { "indexed": false, "internalType": "address[]", @@ -644,6 +821,12 @@ "name": "endBlock", "type": "uint256" }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatePeriodEndBlock", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -1047,6 +1230,31 @@ "name": "VoteCast", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "clientId", + "type": "uint32" + } + ], + "name": "VoteCastWithClientId", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1148,6 +1356,10 @@ "name": "WithdrawFromForkEscrow", "type": "event" }, + { + "stateMutability": "payable", + "type": "fallback" + }, { "inputs": [], "name": "MAX_PROPOSAL_THRESHOLD_BPS", @@ -1228,21 +1440,39 @@ }, { "inputs": [], - "name": "_acceptAdmin", - "outputs": [], - "stateMutability": "nonpayable", + "name": "adjustedTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "_acceptVetoer", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "cancel", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "_burnVetoPower", + "inputs": [ + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + } + ], + "name": "cancelSig", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1250,350 +1480,40 @@ { "inputs": [ { - "internalType": "uint16", - "name": "newMinQuorumVotesBPS", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "newMaxQuorumVotesBPS", - "type": "uint16" + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" }, { - "internalType": "uint32", - "name": "newQuorumCoefficient", - "type": "uint32" + "internalType": "uint8", + "name": "support", + "type": "uint8" } ], - "name": "_setDynamicQuorumParams", + "name": "castRefundableVote", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address[]", - "name": "erc20tokens", - "type": "address[]" - } - ], - "name": "_setErc20TokensToIncludeInFork", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newForkDAODeployer", - "type": "address" - } - ], - "name": "_setForkDAODeployer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newForkEscrow", - "type": "address" - } - ], - "name": "_setForkEscrow", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forkEscrow_", - "type": "address" - }, - { - "internalType": "address", - "name": "forkDAODeployer_", - "type": "address" - }, - { - "internalType": "address[]", - "name": "erc20TokensToIncludeInFork_", - "type": "address[]" - }, { "internalType": "uint256", - "name": "forkPeriod_", + "name": "proposalId", "type": "uint256" }, { - "internalType": "uint256", - "name": "forkThresholdBPS_", - "type": "uint256" - } - ], - "name": "_setForkParams", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newForkPeriod", - "type": "uint256" - } - ], - "name": "_setForkPeriod", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newForkThresholdBPS", - "type": "uint256" - } - ], - "name": "_setForkThresholdBPS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "newLastMinuteWindowInBlocks", - "type": "uint32" - } - ], - "name": "_setLastMinuteWindowInBlocks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "newMaxQuorumVotesBPS", - "type": "uint16" - } - ], - "name": "_setMaxQuorumVotesBPS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "newMinQuorumVotesBPS", - "type": "uint16" - } - ], - "name": "_setMinQuorumVotesBPS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "newObjectionPeriodDurationInBlocks", - "type": "uint32" - } - ], - "name": "_setObjectionPeriodDurationInBlocks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newPendingAdmin", - "type": "address" - } - ], - "name": "_setPendingAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newPendingVetoer", - "type": "address" - } - ], - "name": "_setPendingVetoer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newProposalThresholdBPS", - "type": "uint256" - } - ], - "name": "_setProposalThresholdBPS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "newProposalUpdatablePeriodInBlocks", - "type": "uint32" - } - ], - "name": "_setProposalUpdatablePeriodInBlocks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "uint8", + "name": "support", + "type": "uint8" + }, { "internalType": "uint32", - "name": "newQuorumCoefficient", + "name": "clientId", "type": "uint32" } ], - "name": "_setQuorumCoefficient", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newTimelock", - "type": "address" - }, - { - "internalType": "address", - "name": "newTimelockV1", - "type": "address" - }, - { - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "_setTimelocksAndAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "_setVoteSnapshotBlockSwitchProposalId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newVotingDelay", - "type": "uint256" - } - ], - "name": "_setVotingDelay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "newVotingPeriod", - "type": "uint256" - } - ], - "name": "_setVotingPeriod", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "_withdraw", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "adjustedTotalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "cancel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "sig", - "type": "bytes" - } - ], - "name": "cancelSig", + "name": "castRefundableVote", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1609,9 +1529,14 @@ "internalType": "uint8", "name": "support", "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" } ], - "name": "castRefundableVote", + "name": "castRefundableVoteWithReason", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1632,6 +1557,11 @@ "internalType": "string", "name": "reason", "type": "string" + }, + { + "internalType": "uint32", + "name": "clientId", + "type": "uint32" } ], "name": "castRefundableVoteWithReason", @@ -1722,7 +1652,7 @@ }, { "internalType": "uint256", - "name": "totalSupply", + "name": "adjustedTotalSupply_", "type": "uint256" }, { @@ -1826,19 +1756,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "executeOnTimelockV1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "forkDAODeployer", @@ -2182,7 +2099,91 @@ { "internalType": "uint256", "name": "", - "type": "uint256" + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minQuorumVotes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nouns", + "outputs": [ + { + "internalType": "contract NounsTokenLike", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numTokensInForkEscrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "objectionPeriodDurationInBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingVetoer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalClientId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" } ], "stateMutability": "view", @@ -2190,7 +2191,7 @@ }, { "inputs": [], - "name": "minQuorumVotes", + "name": "proposalCount", "outputs": [ { "internalType": "uint256", @@ -2202,13 +2203,66 @@ "type": "function" }, { - "inputs": [], - "name": "nouns", + "inputs": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + } + ], + "name": "proposalDataForRewards", "outputs": [ { - "internalType": "contract NounsTokenLike", + "components": [ + { + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "objectionPeriodEndBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "abstainVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "clientId", + "type": "uint32" + } + ], + "internalType": "struct NounsDAOStorageV3.ProposalForRewards", "name": "", - "type": "address" + "type": "tuple" } ], "stateMutability": "view", @@ -2216,7 +2270,7 @@ }, { "inputs": [], - "name": "numTokensInForkEscrow", + "name": "proposalMaxOperations", "outputs": [ { "internalType": "uint256", @@ -2224,12 +2278,12 @@ "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { "inputs": [], - "name": "objectionPeriodDurationInBlocks", + "name": "proposalThreshold", "outputs": [ { "internalType": "uint256", @@ -2242,12 +2296,12 @@ }, { "inputs": [], - "name": "pendingVetoer", + "name": "proposalThresholdBPS", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", @@ -2255,7 +2309,7 @@ }, { "inputs": [], - "name": "proposalCount", + "name": "proposalUpdatablePeriodInBlocks", "outputs": [ { "internalType": "uint256", @@ -2267,52 +2321,72 @@ "type": "function" }, { - "inputs": [], - "name": "proposalMaxOperations", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "proposalId", "type": "uint256" + }, + { + "internalType": "uint32", + "name": "clientId", + "type": "uint32" } ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "proposalThreshold", + "name": "proposalVoteClientData", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "uint32", + "name": "votes", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "txs", + "type": "uint32" + } + ], + "internalType": "struct NounsDAOStorageV3.ClientVoteData", "name": "", - "type": "uint256" + "type": "tuple" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "proposalThresholdBPS", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "proposalId", "type": "uint256" + }, + { + "internalType": "uint32[]", + "name": "clientIds", + "type": "uint32[]" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proposalUpdatablePeriodInBlocks", + "name": "proposalVoteClientsData", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "uint32", + "name": "votes", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "txs", + "type": "uint32" + } + ], + "internalType": "struct NounsDAOStorageV3.ClientVoteData[]", "name": "", - "type": "uint256" + "type": "tuple[]" } ], "stateMutability": "view", @@ -2501,6 +2575,11 @@ "name": "creationBlock", "type": "uint256" }, + { + "internalType": "uint256", + "name": "creationTimestamp", + "type": "uint256" + }, { "internalType": "address[]", "name": "signers", @@ -2530,6 +2609,50 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "uint32", + "name": "clientId", + "type": "uint32" + } + ], + "name": "propose", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2630,6 +2753,72 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + }, + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "expirationTimestamp", + "type": "uint256" + } + ], + "internalType": "struct NounsDAOStorageV3.ProposerSignature[]", + "name": "proposerSignatures", + "type": "tuple[]" + }, + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "uint32", + "name": "clientId", + "type": "uint32" + } + ], + "name": "proposeBySigs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -3096,7 +3285,20 @@ "type": "address" } ], - "name": "withdrawDAONounsFromEscrow", + "name": "withdrawDAONounsFromEscrowIncreasingTotalSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "withdrawDAONounsFromEscrowToTreasury", "outputs": [], "stateMutability": "nonpayable", "type": "function" diff --git a/packages/nouns-contracts/contracts/governance/NounsDAOInterfaces.sol b/packages/nouns-contracts/contracts/governance/NounsDAOInterfaces.sol index bafba2ede8..9ad0279446 100644 --- a/packages/nouns-contracts/contracts/governance/NounsDAOInterfaces.sol +++ b/packages/nouns-contracts/contracts/governance/NounsDAOInterfaces.sol @@ -258,6 +258,11 @@ contract NounsDAOEventsV3 is NounsDAOEventsV2 { /// @notice Emitted when withdrawing nouns from escrow increases adjusted total supply event DAONounsSupplyIncreasedFromEscrow(uint256 numTokens, address to); + + /// @notice An event emitted when a vote has been cast with a non-zero client Id. + /// @dev Assumes the `VoteCast` event is emitted, and that indexers can use the voter address and propose ID to + /// find the relevant vote and set its client ID. + event VoteCastWithClientId(address indexed voter, uint256 indexed proposalId, uint32 indexed clientId); } contract NounsDAOProxyStorage { diff --git a/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol b/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol index 87d5b47409..29d3021a3e 100644 --- a/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol +++ b/packages/nouns-contracts/contracts/governance/NounsDAOV3Votes.sol @@ -128,6 +128,7 @@ library NounsDAOV3Votes { uint256 startGas = gasleft(); uint96 votes = castVoteInternal(ds, msg.sender, proposalId, support, clientId); emit VoteCast(msg.sender, proposalId, support, votes, reason); + if (clientId > 0) emit NounsDAOEventsV3.VoteCastWithClientId(msg.sender, proposalId, clientId); if (votes > 0) { _refundGas(startGas); } diff --git a/packages/nouns-subgraph/schema.graphql b/packages/nouns-subgraph/schema.graphql index d1ef51a08c..f2e469d70c 100644 --- a/packages/nouns-subgraph/schema.graphql +++ b/packages/nouns-subgraph/schema.graphql @@ -381,6 +381,9 @@ type Vote @entity { "The timestamp of the block the vote is in" blockTimestamp: BigInt! + + "The ID of the client that facilitated this vote" + clientId: Int! } type Governance @entity { diff --git a/packages/nouns-subgraph/src/custom-types/ParsedProposalV3.ts b/packages/nouns-subgraph/src/custom-types/ParsedProposalV3.ts index abfdccc3bf..569c1f6d50 100644 --- a/packages/nouns-subgraph/src/custom-types/ParsedProposalV3.ts +++ b/packages/nouns-subgraph/src/custom-types/ParsedProposalV3.ts @@ -29,7 +29,7 @@ export class ParsedProposalV3 { signers: string[] = []; adjustedTotalSupply: BigInt = BIGINT_ZERO; - static fromV1Event(event: ProposalCreatedWithRequirements1): ParsedProposalV3 { + static fromV1Event(event: ProposalCreatedWithRequirements): ParsedProposalV3 { const proposal = new ParsedProposalV3(); proposal.id = event.params.id.toString(); @@ -54,7 +54,7 @@ export class ParsedProposalV3 { return proposal; } - static fromV3Event(event: ProposalCreatedWithRequirements): ParsedProposalV3 { + static fromV3Event(event: ProposalCreatedWithRequirements1): ParsedProposalV3 { const proposal = new ParsedProposalV3(); const nounsDAO = NounsDAO.bind(event.address); diff --git a/packages/nouns-subgraph/src/nouns-dao.ts b/packages/nouns-subgraph/src/nouns-dao.ts index 7d8c523111..46236f654a 100644 --- a/packages/nouns-subgraph/src/nouns-dao.ts +++ b/packages/nouns-subgraph/src/nouns-dao.ts @@ -1,4 +1,4 @@ -import { Bytes, log, ethereum, store, BigInt } from '@graphprotocol/graph-ts'; +import { Bytes, log, ethereum, store, BigInt, Address } from '@graphprotocol/graph-ts'; import { ProposalCreatedWithRequirements, ProposalCreatedWithRequirements1, @@ -21,6 +21,7 @@ import { JoinFork, ProposalCreatedOnTimelockV1, VoteSnapshotBlockSwitchProposalIdSet, + VoteCastWithClientId, } from './types/NounsDAO/NounsDAO'; import { getOrCreateDelegate, @@ -57,13 +58,13 @@ import { } from './types/schema'; export function handleProposalCreatedWithRequirements( - event: ProposalCreatedWithRequirements1, + event: ProposalCreatedWithRequirements, ): void { handleProposalCreated(ParsedProposalV3.fromV1Event(event)); } export function handleProposalCreatedWithRequirementsV3( - event: ProposalCreatedWithRequirements, + event: ProposalCreatedWithRequirements1, ): void { handleProposalCreated(ParsedProposalV3.fromV3Event(event)); } @@ -263,10 +264,7 @@ export function handleProposalExecuted(event: ProposalExecuted): void { export function handleVoteCast(event: VoteCast): void { let proposal = getOrCreateProposal(event.params.proposalId.toString()); - let voteId = event.params.voter - .toHexString() - .concat('-') - .concat(event.params.proposalId.toString()); + let voteId = generateVoteId(event.params.voter, event.params.proposalId); let vote = getOrCreateVote(voteId); let voterResult = getOrCreateDelegateWithNullOption(event.params.voter.toHexString()); @@ -326,6 +324,13 @@ export function handleVoteCast(event: VoteCast): void { proposal.save(); } +export function handleVoteCastWithClientId(event: VoteCastWithClientId): void { + let voteId = generateVoteId(event.params.voter, event.params.proposalId); + let vote = getOrCreateVote(voteId); + vote.clientId = event.params.clientId.toI32(); + vote.save(); +} + export function handleMinQuorumVotesBPSSet(event: MinQuorumVotesBPSSet): void { const params = getOrCreateDynamicQuorumParams(event.block.number); params.minQuorumVotesBPS = event.params.newMinQuorumVotesBPS; @@ -513,3 +518,7 @@ export function handleVoteSnapshotBlockSwitchProposalIdSet( function genericUniqueId(event: ethereum.Event): string { return event.transaction.hash.toHexString().concat('-').concat(event.logIndex.toString()); } + +function generateVoteId(voter: Address, proposalId: BigInt): string { + return voter.toHexString().concat('-').concat(proposalId.toString()); +} diff --git a/packages/nouns-subgraph/subgraph.yaml.mustache b/packages/nouns-subgraph/subgraph.yaml.mustache index 2d37f32e4f..bdda25c726 100644 --- a/packages/nouns-subgraph/subgraph.yaml.mustache +++ b/packages/nouns-subgraph/subgraph.yaml.mustache @@ -128,6 +128,8 @@ dataSources: handler: handleJoinFork - event: VoteSnapshotBlockSwitchProposalIdSet(uint256,uint256) handler: handleVoteSnapshotBlockSwitchProposalIdSet + - event: VoteCastWithClientId(indexed address,indexed uint256,indexed uint32) + handler: handleVoteCastWithClientId - kind: ethereum/contract name: NounsDAOData network: {{network}}