diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 123833fe..b7bf0efd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -49,7 +49,7 @@ jobs: run: yarn test integration-test-isolated-pools: - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 needs: unit-test steps: - name: Checkout @@ -82,7 +82,7 @@ jobs: docker system prune -f -a --volumes integration-test-governance: - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 needs: unit-test steps: - name: Checkout @@ -107,7 +107,7 @@ jobs: - name: Run Governance integration integration tests run: | docker exec -i subgraph-hardhat-node yarn workspace venus-governance-subgraph run test:integration --bail - + - name: Stop containers if: always() run: | diff --git a/copy_contracts.sh b/copy_contracts.sh index 91a83cc3..898a20e4 100755 --- a/copy_contracts.sh +++ b/copy_contracts.sh @@ -20,6 +20,7 @@ mkdir -p ./contracts/governance/contracts/Governance mkdir -p ./contracts/governance/contracts/legacy cp ./node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorBravoDelegateV1.sol ./contracts/governance/contracts/legacy/GovernorBravoDelegateV1.sol cp ./node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorBravoInterfaces.sol ./contracts/governance/contracts/legacy/GovernorBravoInterfaces.sol +cp ./node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorBravoDelegator.sol ./contracts/governance/contracts/legacy/GovernorBravoDelegator.sol cp ./node_modules/@venusprotocol/governance-contracts/contracts/Governance/GovernorBravoInterfaces.sol ./contracts/governance/contracts/Governance/GovernorBravoInterfaces.sol rm contracts/protocol/contracts/Governance/GovernorBravoDelegate.sol diff --git a/deploy/017-vaults.ts b/deploy/017-vaults.ts index e2bf9dd3..dea9a028 100644 --- a/deploy/017-vaults.ts +++ b/deploy/017-vaults.ts @@ -40,23 +40,25 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { autoMine: true, }); - const xvsVault = await ethers.getContract('XVSVault'); + let xvsVault = await ethers.getContract('XVSVault'); const xvsStore = await ethers.getContract('XVSStore'); const xvsVaultProxy = await ethers.getContract('XVSVaultProxy'); const accessControlManager = await ethers.getContract('AccessControlManager'); + // Become Implementation of XVSVaultProxy + await xvsVaultProxy._setPendingImplementation(xvsVaultAddress); + await xvsVault._become(xvsVaultProxyAddress); + + xvsVault = await ethers.getContractAt('XVSVault', xvsVaultProxyAddress); + let txn = await xvsVault.setXvsStore(xvsAddress, xvsStore.address); await txn.wait(1); txn = await xvsVault.setAccessControl(accessControlManager.address); await txn.wait(1); - // Become Implementation of XVSVaultProxy - await xvsVaultProxy._setPendingImplementation(xvsVaultAddress); - await xvsVault._become(xvsVaultProxyAddress); - // Set new owner to xvs store - await xvsStore.setNewOwner(xvsVaultAddress); + await xvsStore.setNewOwner(xvsVaultProxyAddress); }; func.tags = ['XVS vault']; diff --git a/deploy/018-governance.ts b/deploy/018-governance.ts index dd25cc7f..6dfdd8e0 100644 --- a/deploy/018-governance.ts +++ b/deploy/018-governance.ts @@ -1,4 +1,4 @@ -import { ethers } from 'hardhat'; +import { ethers, network } from 'hardhat'; import { DeployFunction } from 'hardhat-deploy/types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; @@ -6,66 +6,120 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; const { deploy } = deployments; const { deployer } = await getNamedAccounts(); + const signers = await ethers.getSigners(); const timelock = await ethers.getContract('Timelock'); - const xvsVault = await ethers.getContract('XVSVault'); + const xvsVault = await ethers.getContract('XVSVaultProxy'); + await deploy('GovernorAlphaTimelock', { + contract: 'Timelock', + from: deployer, + args: [deployer, 3600], + log: true, + autoMine: true, + }); + + const governorAlphaTimelock = await ethers.getContract('GovernorAlphaTimelock'); await deploy('GovernorAlpha', { from: deployer, - args: [timelock.address, xvsVault.address, deployer], + args: [governorAlphaTimelock.address, xvsVault.address, deployer], + log: true, + autoMine: true, + }); + const governorAlpha = await ethers.getContract('GovernorAlpha'); + + await signers[0].sendTransaction({ + to: governorAlphaTimelock.address, + value: ethers.utils.parseEther('1.0'), + }); + + await network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [governorAlphaTimelock.address], + }); + const signer = await ethers.getSigner(governorAlphaTimelock.address); + + await governorAlphaTimelock.connect(signer).setPendingAdmin(governorAlpha.address); + await network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [governorAlphaTimelock.address], + }); + + await governorAlpha.__acceptAdmin(); + + await deploy('GovernorAlpha2Timelock', { + contract: 'Timelock', + from: deployer, + args: [deployer, 3600], log: true, autoMine: true, }); + const governorAlpha2Timelock = await ethers.getContract('GovernorAlpha2Timelock'); + await deploy('GovernorAlpha2', { from: deployer, - args: [timelock.address, xvsVault.address, deployer, 20], + args: [governorAlpha2Timelock.address, xvsVault.address, deployer, 20], log: true, autoMine: true, }); - const governorBravoDelegateDeployment = await deploy('GovernorBravoDelegate', { + const governorAlpha2 = await ethers.getContract('GovernorAlpha2'); + + await signers[0].sendTransaction({ + to: governorAlpha2Timelock.address, + value: ethers.utils.parseEther('1.0'), + }); + + await network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [governorAlpha2Timelock.address], + }); + const governorAlpha2Signer = await ethers.getSigner(governorAlpha2Timelock.address); + + await governorAlpha2Timelock + .connect(governorAlpha2Signer) + .setPendingAdmin(governorAlpha2.address); + + await network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [governorAlpha2Timelock.address], + }); + + await governorAlpha2.__acceptAdmin(); + + const governorBravoDelegateV1Deployment = await deploy('GovernorBravoDelegateV1', { from: deployer, args: [], log: true, autoMine: true, }); - const governorBravoDelegate = await ethers.getContractAt( - 'GovernorBravoDelegate', - governorBravoDelegateDeployment.address, - ); + await deploy('GovernorBravoDelegateV2', { + contract: + '@venusprotocol/governance-contracts/contracts/Governance/GovernorBravoDelegate.sol:GovernorBravoDelegate', + from: deployer, + args: [], + log: true, + autoMine: true, + }); + + const governorBravoDelegate = await ethers.getContract('GovernorBravoDelegateV2'); + const minVotingDelay = await governorBravoDelegate.MIN_VOTING_DELAY(); const minVotingPeriod = await governorBravoDelegate.MIN_VOTING_PERIOD(); const minProposalThreshold = await governorBravoDelegate.MIN_PROPOSAL_THRESHOLD(); - const proposalConfigs = [ - { - votingDelay: minVotingDelay.add(3), - votingPeriod: minVotingPeriod.add(3), - proposalThreshold: minProposalThreshold.add(3), - }, - { - votingDelay: minVotingDelay.add(2), - votingPeriod: minVotingPeriod.add(2), - proposalThreshold: minProposalThreshold.add(2), - }, - { - votingDelay: minVotingDelay.add(1), - votingPeriod: minVotingPeriod.add(1), - proposalThreshold: minProposalThreshold.add(1), - }, - ]; - - const timelocks = [timelock.address, timelock.address, timelock.address]; - - await deploy('GovernorBravoDelegator', { + + await deploy('GovernorBravoDelegatorV1', { from: deployer, args: [ + timelock.address, xvsVault.address, deployer, - governorBravoDelegate.address, - proposalConfigs, - timelocks, + governorBravoDelegateV1Deployment.address, + minVotingPeriod.toString(), + minVotingDelay.toString(), + minProposalThreshold.toString(), deployer, ], log: true, diff --git a/deploy/019-configure-vaults.ts b/deploy/019-configure-vaults.ts index f911ecda..b9abe571 100644 --- a/deploy/019-configure-vaults.ts +++ b/deploy/019-configure-vaults.ts @@ -7,7 +7,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await getNamedAccounts(); const accessControlManager = await ethers.getContract('AccessControlManager'); - const xvsVault = await ethers.getContract('XVSVault'); + const xvsVaultProxy = await ethers.getContract('XVSVaultProxy'); + const xvsVault = await ethers.getContractAt('XVSVault', xvsVaultProxy.address); const xvs = await ethers.getContract('XVS'); const tx = await accessControlManager.giveCallPermission( diff --git a/docker-compose.yaml b/docker-compose.yaml index a7bcee46..4e0add86 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -15,11 +15,6 @@ services: condition: service_started postgres: condition: service_started - healthcheck: - test: ["CMD", "curl", "-f", "http://graph-node:8000"] - interval: 30s - timeout: 12s - retries: 10 environment: postgres_host: postgres postgres_user: graph-node @@ -38,7 +33,7 @@ services: - sh - -c - | - yarn &&PACKAGE=isolated-pools yarn workspace isolated-pools-subgraph run hardhat node --hostname 0.0.0.0 + yarn && PACKAGE=isolated-pools yarn run node:integration # Installing again to link workspaces ports: - 8545:8545 diff --git a/hardhat.config.ts b/hardhat.config.ts index f9770971..254fec5c 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -95,6 +95,9 @@ const config: HardhatUserConfig = { '@venusprotocol/governance-contracts/contracts/Governance/GovernorBravoDelegator.sol', ], }, + mocha: { + timeout: 100000000 + }, // Hardhat deploy namedAccounts: { deployer: 0, // here this will by default take the first account as deployer diff --git a/package.json b/package.json index a8812d74..5a8c4d57 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "lint:fix": "yarn lint --fix", "pretty": "prettier '**/*.ts' --write", "test": "yarn workspaces foreach run test", + "node:integration": "PACKAGE=isolated-pools hardhat node --hostname 0.0.0.0", "test:integration": "yarn workspaces foreach run test:integration", "postinstall": "patch-package && ./copy_contracts.sh" }, diff --git a/patches/@venusprotocol+governance-contracts+1.3.0.patch b/patches/@venusprotocol+governance-contracts+1.3.0.patch new file mode 100644 index 00000000..5bace989 --- /dev/null +++ b/patches/@venusprotocol+governance-contracts+1.3.0.patch @@ -0,0 +1,133 @@ +diff --git a/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha.sol b/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha.sol +index fca5350..4713034 100644 +--- a/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha.sol ++++ b/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha.sol +@@ -27,8 +27,8 @@ contract GovernorAlpha { + + /// @notice The duration of voting on a proposal, in blocks + function votingPeriod() public pure returns (uint) { +- return (60 * 60 * 24 * 3) / 3; +- } // ~3 days in blocks (assuming 3s blocks) ++ return 100; ++ } // A reasonable amount of block suitable for testing + + /// @notice The address of the Venus Protocol Timelock + TimelockInterface public timelock; +diff --git a/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha2.sol b/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha2.sol +index c009718..0e8e8ec 100644 +--- a/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha2.sol ++++ b/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorAlpha2.sol +@@ -27,8 +27,8 @@ contract GovernorAlpha2 { + + /// @notice The duration of voting on a proposal, in blocks + function votingPeriod() public pure returns (uint) { +- return (60 * 60 * 24 * 3) / 3; +- } // ~3 days in blocks (assuming 3s blocks) ++ return 100; ++ } // A reasonable amount of block suitable for testing + + /// @notice The address of the Venus Protocol Timelock + TimelockInterface public timelock; +diff --git a/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorBravoDelegator.sol b/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorBravoDelegator.sol +new file mode 100644 +index 0000000..4323517 +--- /dev/null ++++ b/node_modules/@venusprotocol/governance-contracts/contracts/legacy/GovernorBravoDelegator.sol +@@ -0,0 +1,97 @@ ++pragma solidity ^0.5.16; ++pragma experimental ABIEncoderV2; ++ ++import "./GovernorBravoInterfaces.sol"; ++ ++/** ++ * @title GovernorBravoDelegator ++ * @author Venus ++ * @notice The `GovernorBravoDelegator` contract. ++ */ ++contract GovernorBravoDelegatorV1 is GovernorBravoDelegatorStorage, GovernorBravoEventsV1 { ++ constructor( ++ address timelock_, ++ address xvsVault_, ++ address admin_, ++ address implementation_, ++ uint votingPeriod_, ++ uint votingDelay_, ++ uint proposalThreshold_, ++ address guardian_ ++ ) public { ++ // Admin set to msg.sender for initialization ++ admin = msg.sender; ++ ++ delegateTo( ++ implementation_, ++ abi.encodeWithSignature( ++ "initialize(address,address,uint256,uint256,uint256,address)", ++ timelock_, ++ xvsVault_, ++ votingPeriod_, ++ votingDelay_, ++ proposalThreshold_, ++ guardian_ ++ ) ++ ); ++ ++ _setImplementation(implementation_); ++ ++ admin = admin_; ++ } ++ ++ /** ++ * @notice Called by the admin to update the implementation of the delegator ++ * @param implementation_ The address of the new implementation for delegation ++ */ ++ function _setImplementation(address implementation_) public { ++ require(msg.sender == admin, "GovernorBravoDelegator::_setImplementation: admin only"); ++ require( ++ implementation_ != address(0), ++ "GovernorBravoDelegator::_setImplementation: invalid implementation address" ++ ); ++ ++ address oldImplementation = implementation; ++ implementation = implementation_; ++ ++ emit NewImplementation(oldImplementation, implementation); ++ } ++ ++ /** ++ * @notice Internal method to delegate execution to another contract ++ * @dev It returns to the external caller whatever the implementation returns or forwards reverts ++ * @param callee The contract to delegatecall ++ * @param data The raw data to delegatecall ++ */ ++ function delegateTo(address callee, bytes memory data) internal { ++ (bool success, bytes memory returnData) = callee.delegatecall(data); ++ assembly { ++ if eq(success, 0) { ++ revert(add(returnData, 0x20), returndatasize) ++ } ++ } ++ } ++ ++ /** ++ * @dev Delegates execution to an implementation contract. ++ * It returns to the external caller whatever the implementation returns ++ * or forwards reverts. ++ */ ++ function() external payable { ++ // delegate all other functions to current implementation ++ (bool success, ) = implementation.delegatecall(msg.data); ++ ++ assembly { ++ let free_mem_ptr := mload(0x40) ++ returndatacopy(free_mem_ptr, 0, returndatasize) ++ ++ switch success ++ case 0 { ++ revert(free_mem_ptr, returndatasize) ++ } ++ default { ++ return(free_mem_ptr, returndatasize) ++ } ++ } ++ } ++} diff --git a/subgraphs/isolated-pools/package.json b/subgraphs/isolated-pools/package.json index 7f0ea0a4..f42016f9 100644 --- a/subgraphs/isolated-pools/package.json +++ b/subgraphs/isolated-pools/package.json @@ -31,7 +31,6 @@ "generate-subgraph-types": "rm -rf /subgraph-client/.graphclient && yarn graphclient build --dir ./subgraph-client", "pretty": "prettier —-write '**/*.ts'", "test": "yarn prepare:local && graph test", - "node:integration": "PACKAGE=isolated-pools hardhat node --hostname 0.0.0.0", "test:integration": "PACKAGE=isolated-pools hardhat test tests/integration/index.ts --network localhost" }, "devDependencies": { diff --git a/subgraphs/venus-governance/config/bsc.json b/subgraphs/venus-governance/config/bsc.json index 56b6a60b..1deb277e 100644 --- a/subgraphs/venus-governance/config/bsc.json +++ b/subgraphs/venus-governance/config/bsc.json @@ -6,8 +6,8 @@ "governorAlphaStartBlock": "2474351", "governorAlpha2Address": "0x388313BfEFEE8ddfeAD55b585F62812293Cf3A60", "governorAlpha2StartBlock": "11934064", - "governorBravoDelegateAddress": "0x2d56dC077072B53571b8252008C60e945108c75a", - "governorBravoDelegateStartBlock": "13729317", + "governorBravoDelegatorAddress": "0x2d56dC077072B53571b8252008C60e945108c75a", + "governorBravoDelegatorStartBlock": "13729317", "xvsVaultAddress": "0x6eF49b4e0772Fe78128F981d42D54172b55eCF9F", "xvsVaultStartBlock": "13018718", "xvsVaultPid": "0" diff --git a/subgraphs/venus-governance/config/chapel.json b/subgraphs/venus-governance/config/chapel.json index bd725faf..8b008e4b 100644 --- a/subgraphs/venus-governance/config/chapel.json +++ b/subgraphs/venus-governance/config/chapel.json @@ -6,8 +6,8 @@ "governorAlphaStartBlock": "8205736", "governorAlpha2Address": "0x7116894ed34FC4B27D5b84f46B70Af48397a6C24", "governorAlpha2StartBlock": "13584539", - "governorBravoDelegateAddress": "0x5573422a1a59385c247ec3a66b93b7c08ec2f8f2", - "governorBravoDelegateStartBlock": "16002994", + "governorBravoDelegatorAddress": "0x5573422a1a59385c247ec3a66b93b7c08ec2f8f2", + "governorBravoDelegatorStartBlock": "16002994", "xvsVaultAddress": "0xa4Fd54cACdA379FB7CaA783B83Cc846f8ac0Faa6", "xvsVaultStartBlock": "13937802", "xvsVaultPid": "1" diff --git a/subgraphs/venus-governance/config/local.json b/subgraphs/venus-governance/config/local.json index e3ed3413..e775d591 100644 --- a/subgraphs/venus-governance/config/local.json +++ b/subgraphs/venus-governance/config/local.json @@ -2,13 +2,13 @@ "network": "hardhat", "accessControlManagerAddress": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", "accessControlManagerStartBlock": "0", - "governorAlphaAddress": "0x1c9fD50dF7a4f066884b58A05D91e4b55005876A", + "governorAlphaAddress": "0x0fe4223AD99dF788A6Dcad148eB4086E6389cEB6", "governorAlphaStartBlock": "0", - "governorAlpha2Address": "0x0fe4223AD99dF788A6Dcad148eB4086E6389cEB6", + "governorAlpha2Address": "0x193521c8934bcf3473453af4321911e7a89e0e12", "governorAlpha2StartBlock": "0", - "governorBravoDelegateAddress": "0x1c9fD50dF7a4f066884b58A05D91e4b55005876A", - "governorBravoDelegateStartBlock": "0", - "xvsVaultAddress": "0x967AB65ef14c58bD4DcfFeaAA1ADb40a022140E5", + "governorBravoDelegatorAddress": "0x22a9b82a6c3d2bfb68f324b2e8367f346dd6f32a", + "governorBravoDelegatorStartBlock": "0", + "xvsVaultAddress": "0xe1708FA6bb2844D5384613ef0846F9Bc1e8eC55E", "xvsVaultStartBlock": "0", "xvsVaultPid": "0" } diff --git a/subgraphs/venus-governance/schema.graphql b/subgraphs/venus-governance/schema.graphql index 85413e1d..39e3bb26 100644 --- a/subgraphs/venus-governance/schema.graphql +++ b/subgraphs/venus-governance/schema.graphql @@ -1,11 +1,3 @@ -enum ProposalStatus { - PENDING - ACTIVE - CANCELLED - QUEUED - EXECUTED -} - type Delegate @entity { "A Delegate is any address that has been delegated with voting tokens by a token holder, id is the blockchain address of said delegate" id: ID! @@ -66,11 +58,17 @@ type Proposal @entity { "String description of the change" description: String! - "Status of the proposal" - status: ProposalStatus! - "Once the proposal is queued for execution it will have an ETA of the execution" - executionETA: BigInt + executionEta: BigInt + + "Whether a proposal has been queued" + queued: Boolean + + "Whether a proposal has been canceled" + canceled: Boolean + + "Whether a proposal has been executed" + executed: Boolean "Votes associated to this proposal" votes: [Vote!]! @derivedFrom(field: "proposal") @@ -117,9 +115,6 @@ type Governance @entity { "Total number of votes delegated expressed in the smallest unit of XVS" totalVotesMantissa: BigInt! - - "Number of proposals currently queued for execution" - proposalsQueued: BigInt! "The number of votes required to reach quorum" quorumVotesMantissa: BigInt! diff --git a/subgraphs/venus-governance/src/constants/addresses.ts b/subgraphs/venus-governance/src/constants/addresses.ts index 4631b68e..a238fc9b 100644 --- a/subgraphs/venus-governance/src/constants/addresses.ts +++ b/subgraphs/venus-governance/src/constants/addresses.ts @@ -1,7 +1,9 @@ import { Address } from '@graphprotocol/graph-ts'; -import { governorBravoDelegateAddress as governorBravoDelegateAddressString } from './config'; +import { governorBravoDelegatorAddress as governorBravoDelegatorAddressString } from './config'; -export const governorBravoDelegateAddress = Address.fromString(governorBravoDelegateAddressString); +export const governorBravoDelegatorAddress = Address.fromString( + governorBravoDelegatorAddressString, +); export const nullAddress = Address.fromString('0x0000000000000000000000000000000000000000'); diff --git a/subgraphs/venus-governance/src/constants/config-template b/subgraphs/venus-governance/src/constants/config-template index a03bacde..d3e9f71d 100644 --- a/subgraphs/venus-governance/src/constants/config-template +++ b/subgraphs/venus-governance/src/constants/config-template @@ -1,6 +1,6 @@ // Use yarn prepare commands to generate config typescript file per env -export const governorBravoDelegateAddress = '{{ governorBravoDelegateAddress }}'; +export const governorBravoDelegatorAddress = '{{ governorBravoDelegatorAddress }}'; export const xvsVaultPid = '{{ xvsVaultPid }}'; diff --git a/subgraphs/venus-governance/src/constants/index.ts b/subgraphs/venus-governance/src/constants/index.ts index 1206978a..0e2165d0 100644 --- a/subgraphs/venus-governance/src/constants/index.ts +++ b/subgraphs/venus-governance/src/constants/index.ts @@ -3,11 +3,6 @@ import { BigDecimal, BigInt } from '@graphprotocol/graph-ts'; export const BIGINT_ZERO = BigInt.fromI32(0); export const BIGINT_ONE = BigInt.fromI32(1); export const BIGDECIMAL_ZERO = new BigDecimal(BIGINT_ZERO); -export const PENDING = 'PENDING'; -export const CANCELLED = 'CANCELLED'; -export const EXECUTED = 'EXECUTED'; -export const QUEUED = 'QUEUED'; -export const ACTIVE = 'ACTIVE'; // Vote support export const FOR = 'FOR'; diff --git a/subgraphs/venus-governance/src/mappings/alpha.ts b/subgraphs/venus-governance/src/mappings/alpha.ts index 0fc8ddc7..eb965c7f 100644 --- a/subgraphs/venus-governance/src/mappings/alpha.ts +++ b/subgraphs/venus-governance/src/mappings/alpha.ts @@ -7,21 +7,19 @@ import { ProposalQueued, VoteCast, } from '../../generated/GovernorAlpha/GovernorAlpha'; -import { ACTIVE, CANCELLED, PENDING } from '../constants'; import { createProposal, createVoteAlpha } from '../operations/create'; -import { getProposal } from '../operations/get'; import { getOrCreateDelegate } from '../operations/getOrCreate'; import { + updateProposalCanceled, updateProposalExecuted, updateProposalQueued, - updateProposalStatus, } from '../operations/update'; // - event: ProposalCreated(uint256,address,address[],uint256[],string[],bytes[],uint256,uint256,string) // handler: handleProposalCreated export function handleProposalCreated(event: ProposalCreated): void { - const result = getOrCreateDelegate(event.params.proposer.toHex()); + const result = getOrCreateDelegate(event.params.proposer); const created = result.created; createProposal(event); @@ -39,8 +37,7 @@ export function handleProposalCreated(event: ProposalCreated): void { // handler: handleProposalCanceled export function handleProposalCanceled(event: ProposalCanceled): void { - const proposalId = event.params.id.toString(); - updateProposalStatus(proposalId, CANCELLED); + updateProposalCanceled(event); } // - event: ProposalQueued(uint256,uint256) @@ -62,20 +59,10 @@ export function handleProposalExecuted(event: ProposalExecuted): void { export function handleVoteCast(event: VoteCast): void { // Alpha V1 doesn't require staking in the vault so we need to create delegates when casting a vote - getOrCreateDelegate(event.params.voter.toHexString()); + getOrCreateDelegate(event.params.voter); createVoteAlpha(event); - const proposalId = event.params.proposalId.toString(); - const proposal = getProposal(proposalId); - if (proposal.status == PENDING) { - updateProposalStatus(proposalId, ACTIVE); - } } export function handleVoteCastV2(event: VoteCast): void { createVoteAlpha(event); - const proposalId = event.params.proposalId.toString(); - const proposal = getProposal(proposalId); - if (proposal.status == PENDING) { - updateProposalStatus(proposalId, ACTIVE); - } } diff --git a/subgraphs/venus-governance/src/mappings/bravo.ts b/subgraphs/venus-governance/src/mappings/bravo.ts index 90c12dba..d5ebaccb 100644 --- a/subgraphs/venus-governance/src/mappings/bravo.ts +++ b/subgraphs/venus-governance/src/mappings/bravo.ts @@ -11,23 +11,23 @@ import { ProposalQueued, VoteCast, } from '../../generated/GovernorBravoDelegate/GovernorBravoDelegate'; -import { ACTIVE, CANCELLED, CRITICAL, FAST_TRACK, NORMAL, PENDING } from '../constants'; +import { CRITICAL, FAST_TRACK, NORMAL } from '../constants'; import { createProposal, createVoteBravo } from '../operations/create'; -import { getGovernanceEntity, getProposal } from '../operations/get'; +import { getGovernanceEntity } from '../operations/get'; import { getOrCreateDelegate } from '../operations/getOrCreate'; import { + updateProposalCanceled, updateProposalExecuted, updateProposalQueued, - updateProposalStatus, } from '../operations/update'; export function handleProposalCreated(event: ProposalCreated): void { - getOrCreateDelegate(event.params.proposer.toHexString()); + getOrCreateDelegate(event.params.proposer); createProposal(event); } export function handleProposalCreatedV2(event: ProposalCreatedV2): void { - getOrCreateDelegate(event.params.proposer.toHexString()); + getOrCreateDelegate(event.params.proposer); const proposal = createProposal(event); const indexProposalTypeConstant = [NORMAL, FAST_TRACK, CRITICAL]; proposal.type = indexProposalTypeConstant[event.params.proposalType]; @@ -35,8 +35,7 @@ export function handleProposalCreatedV2(event: ProposalCreatedV2): void { } export function handleProposalCanceled(event: ProposalCanceled): void { - const proposalId = event.params.id.toString(); - updateProposalStatus(proposalId, CANCELLED); + updateProposalCanceled(event); } export function handleProposalQueued(event: ProposalQueued): void { @@ -49,11 +48,6 @@ export function handleProposalExecuted(event: ProposalExecuted): void { export function handleBravoVoteCast(event: VoteCast): void { createVoteBravo(event); - const proposalId = event.params.proposalId.toString(); - const proposal = getProposal(proposalId); - if (proposal.status == PENDING) { - updateProposalStatus(proposalId, ACTIVE); - } } export function handleNewImplementation(event: NewImplementation): void { diff --git a/subgraphs/venus-governance/src/mappings/xvsVault.ts b/subgraphs/venus-governance/src/mappings/xvsVault.ts index bdd7cbf7..3c529496 100644 --- a/subgraphs/venus-governance/src/mappings/xvsVault.ts +++ b/subgraphs/venus-governance/src/mappings/xvsVault.ts @@ -34,7 +34,7 @@ export function handleDeposit(event: Deposit): void { const user = event.params.user; const amount = event.params.amount; // Update user's staked XVS - const result = getOrCreateDelegate(user.toHex()); + const result = getOrCreateDelegate(user); result.entity.stakedXvsMantissa = result.entity.stakedXvsMantissa.plus(amount); result.entity.save(); } @@ -45,7 +45,7 @@ export function handleRequestedWithdrawal(event: RequestedWithdrawal): void { if (event.params.pid.equals(BigInt.fromString(xvsVaultPid))) { const user = event.params.user; const amount = event.params.amount; - const result = getOrCreateDelegate(user.toHex()); + const result = getOrCreateDelegate(user); const newAmount = result.entity.stakedXvsMantissa.minus(amount); // Update their delegate if (newAmount.equals(new BigInt(0))) { diff --git a/subgraphs/venus-governance/src/operations/create.ts b/subgraphs/venus-governance/src/operations/create.ts index 1d825cf5..2acc7f58 100644 --- a/subgraphs/venus-governance/src/operations/create.ts +++ b/subgraphs/venus-governance/src/operations/create.ts @@ -3,7 +3,7 @@ import { Address, Bytes } from '@graphprotocol/graph-ts'; import { VoteCast as VoteCastAlpha } from '../../generated/GovernorAlpha/GovernorAlpha'; import { VoteCast as VoteCastBravo } from '../../generated/GovernorBravoDelegate/GovernorBravoDelegate'; import { Proposal, Vote } from '../../generated/schema'; -import { ABSTAIN, ACTIVE, AGAINST, BIGINT_ONE, FOR, NORMAL, PENDING } from '../constants'; +import { ABSTAIN, AGAINST, BIGINT_ONE, FOR, NORMAL } from '../constants'; import { getVoteId } from '../utilities/ids'; import { getDelegate, getGovernanceEntity, getProposal } from './get'; @@ -26,7 +26,9 @@ export function createProposal(event: E): Proposal { proposal.startBlock = event.params.startBlock; proposal.endBlock = event.params.endBlock; proposal.description = event.params.description; - proposal.status = event.block.number >= proposal.startBlock ? ACTIVE : PENDING; + proposal.queued = false; + proposal.canceled = false; + proposal.executed = false; proposal.type = NORMAL; proposal.save(); @@ -49,7 +51,7 @@ export function createVoteAlpha(event: VoteCastAlpha): Vote { export function createVoteBravo(event: VoteCastBravo): Vote { const proposal = getProposal(event.params.proposalId.toString()); - const voter = getDelegate(event.params.voter.toHexString()); + const voter = getDelegate(event.params.voter); const id = getVoteId(event.params.voter, event.params.proposalId); const vote = new Vote(id); vote.proposal = proposal.id; diff --git a/subgraphs/venus-governance/src/operations/get.ts b/subgraphs/venus-governance/src/operations/get.ts index 8368f9e1..24711309 100644 --- a/subgraphs/venus-governance/src/operations/get.ts +++ b/subgraphs/venus-governance/src/operations/get.ts @@ -1,25 +1,25 @@ -import { BigInt, log } from '@graphprotocol/graph-ts'; +import { Address, BigInt, log } from '@graphprotocol/graph-ts'; import { GovernorBravoDelegate2 } from '../../generated/GovernorBravoDelegate2/GovernorBravoDelegate2'; import { Timelock } from '../../generated/GovernorBravoDelegate2/Timelock'; import { Delegate, Governance, GovernanceRoute, Proposal } from '../../generated/schema'; import { BIGINT_ZERO } from '../constants'; -import { governorBravoDelegateAddress, nullAddress } from '../constants/addresses'; +import { governorBravoDelegatorAddress, nullAddress } from '../constants/addresses'; +import { getDelegateId } from '../utilities/ids'; /** * While technically this function does also create, we don't care because it only happens once as the id is a constant. * @returns Governance */ export const getGovernanceEntity = (): Governance => { - let governance = Governance.load(governorBravoDelegateAddress.toHex()); + let governance = Governance.load(governorBravoDelegatorAddress.toHex()); if (!governance) { - const governorBravoDelegate2 = GovernorBravoDelegate2.bind(governorBravoDelegateAddress); - governance = new Governance(governorBravoDelegateAddress.toHex()); + const governorBravoDelegate2 = GovernorBravoDelegate2.bind(governorBravoDelegatorAddress); + governance = new Governance(governorBravoDelegatorAddress.toHex()); governance.proposals = BIGINT_ZERO; governance.totalDelegates = BIGINT_ZERO; governance.totalVoters = BIGINT_ZERO; governance.totalVotesMantissa = BIGINT_ZERO; - governance.proposalsQueued = BIGINT_ZERO; // Mocking values until we can correctly index current governance contract governance.admin = nullAddress; governance.implementation = nullAddress; @@ -43,7 +43,7 @@ export const getGovernanceEntity = (): Governance => { const normalTimelockAddress = governorBravoDelegate2.proposalTimelocks(new BigInt(0)); const normalTimelock = Timelock.bind(normalTimelockAddress); const normalGovernanceRoute = new GovernanceRoute('0'); - normalGovernanceRoute.governor = governorBravoDelegateAddress; + normalGovernanceRoute.governor = governorBravoDelegatorAddress; normalGovernanceRoute.timelock = normalTimelockAddress; normalGovernanceRoute.queueDelayBlocks = normalTimelock.delay(); normalGovernanceRoute.votingDelayBlocks = normalProposalConfig.getVotingDelay(); @@ -55,7 +55,7 @@ export const getGovernanceEntity = (): Governance => { const fastTrackTimelockAddress = governorBravoDelegate2.proposalTimelocks(new BigInt(1)); const fastTrackTimelock = Timelock.bind(normalTimelockAddress); const fastTrackGovernanceRoute = new GovernanceRoute('1'); - fastTrackGovernanceRoute.governor = governorBravoDelegateAddress; + fastTrackGovernanceRoute.governor = governorBravoDelegatorAddress; fastTrackGovernanceRoute.timelock = fastTrackTimelockAddress; fastTrackGovernanceRoute.queueDelayBlocks = fastTrackTimelock.delay(); fastTrackGovernanceRoute.votingDelayBlocks = fastTrackProposalConfig.getVotingDelay(); @@ -68,7 +68,7 @@ export const getGovernanceEntity = (): Governance => { const criticalTimelockAddress = governorBravoDelegate2.proposalTimelocks(new BigInt(2)); const criticalTimelock = Timelock.bind(normalTimelockAddress); const criticalGovernanceRoute = new GovernanceRoute('2'); - criticalGovernanceRoute.governor = governorBravoDelegateAddress; + criticalGovernanceRoute.governor = governorBravoDelegatorAddress; criticalGovernanceRoute.timelock = criticalTimelockAddress; criticalGovernanceRoute.queueDelayBlocks = criticalTimelock.delay(); criticalGovernanceRoute.votingDelayBlocks = criticalProposalConfig.getVotingDelay(); @@ -92,7 +92,8 @@ export const getProposal = (id: string): Proposal => { return proposal as Proposal; }; -export const getDelegate = (id: string): Delegate => { +export const getDelegate = (address: Address): Delegate => { + const id = getDelegateId(address); const delegate = Delegate.load(id); if (!delegate) { log.critical('Delegate {} not found', [id]); diff --git a/subgraphs/venus-governance/src/operations/getOrCreate.ts b/subgraphs/venus-governance/src/operations/getOrCreate.ts index 697005a2..a6093ce8 100644 --- a/subgraphs/venus-governance/src/operations/getOrCreate.ts +++ b/subgraphs/venus-governance/src/operations/getOrCreate.ts @@ -1,6 +1,9 @@ +import { Address } from '@graphprotocol/graph-ts'; + import { Delegate } from '../../generated/schema'; import { BIGINT_ONE, BIGINT_ZERO } from '../constants'; import { nullAddress } from '../constants/addresses'; +import { getDelegateId } from '../utilities/ids'; import { getGovernanceEntity } from './get'; export class GetOrCreateDelegateReturn { @@ -8,8 +11,9 @@ export class GetOrCreateDelegateReturn { created: boolean; } -export const getOrCreateDelegate = (id: string): GetOrCreateDelegateReturn => { +export const getOrCreateDelegate = (address: Address): GetOrCreateDelegateReturn => { let created = false; + const id = getDelegateId(address); let delegate = Delegate.load(id); if (!delegate) { delegate = new Delegate(id); diff --git a/subgraphs/venus-governance/src/operations/update.ts b/subgraphs/venus-governance/src/operations/update.ts index 8abdc3f7..90ce90c9 100644 --- a/subgraphs/venus-governance/src/operations/update.ts +++ b/subgraphs/venus-governance/src/operations/update.ts @@ -1,78 +1,69 @@ -import { BIGINT_ONE, BIGINT_ZERO, CANCELLED, EXECUTED, QUEUED } from '../constants'; +import { BIGINT_ONE } from '../constants'; import { nullAddress } from '../constants/addresses'; import { getGovernanceEntity, getProposal } from './get'; import { getOrCreateDelegate } from './getOrCreate'; -export const updateProposalStatus = (id: string, status: string): void => { - const proposal = getProposal(id); - proposal.status = status; - proposal.save(); -}; - export function updateProposalCanceled(event: E): void { const params = event.params; const proposal = getProposal(params.id.toString()); - proposal.status = CANCELLED; + proposal.canceled = true; proposal.save(); } export function updateProposalQueued(event: E): void { const params = event.params; - const governance = getGovernanceEntity(); const proposal = getProposal(params.id.toString()); - proposal.status = QUEUED; - proposal.executionETA = params.eta; + proposal.queued = true; + proposal.executionEta = params.eta; proposal.save(); - - governance.proposalsQueued = governance.proposalsQueued.plus(BIGINT_ONE); - governance.save(); } export function updateProposalExecuted(event: E): void { const params = event.params; - const governance = getGovernanceEntity(); const proposal = getProposal(params.id.toString()); - proposal.status = EXECUTED; - proposal.executionETA = null; + proposal.executed = true; proposal.save(); - - governance.proposalsQueued = governance.proposalsQueued.minus(BIGINT_ONE); - governance.save(); } export function updateDelegateChanged(event: E): void { + const governance = getGovernanceEntity(); const params = event.params; const fromDelegate = params.fromDelegate.toHexString(); const toDelegate = params.toDelegate.toHexString(); - const delegator = params.delegator.toHexString(); - const delegatorResult = getOrCreateDelegate(delegator); + const delegatorResult = getOrCreateDelegate(params.delegator); const delegatorEntity = delegatorResult.entity; delegatorEntity.delegatee = toDelegate; delegatorEntity.save(); if (fromDelegate != nullAddress.toHexString()) { - const oldDelegateResult = getOrCreateDelegate(fromDelegate); + const oldDelegateResult = getOrCreateDelegate(params.fromDelegate); const oldDelegate = oldDelegateResult.entity; oldDelegate.delegateCount = oldDelegate.delegateCount - 1; oldDelegate.save(); + + governance.totalDelegates = governance.totalDelegates.minus(BIGINT_ONE); + governance.save(); } if (toDelegate != nullAddress.toHexString()) { - const newDelegateResult = getOrCreateDelegate(toDelegate); + const newDelegateResult = getOrCreateDelegate(params.toDelegate); const newDelegate = newDelegateResult.entity; newDelegate.delegateCount = newDelegate.delegateCount + 1; newDelegate.save(); + + governance.totalDelegates = governance.totalDelegates.plus(BIGINT_ONE); + governance.save(); } } export function updateDelegateVoteChanged(event: E): void { const params = event.params; const governance = getGovernanceEntity(); - const delegateResult = getOrCreateDelegate(params.delegate.toHexString()); + const delegateResult = getOrCreateDelegate(params.delegate); const delegate = delegateResult.entity; const previousBalance = params.previousBalance; diff --git a/subgraphs/venus-governance/src/utilities/ids.ts b/subgraphs/venus-governance/src/utilities/ids.ts index 66ec202f..6db7fd40 100644 --- a/subgraphs/venus-governance/src/utilities/ids.ts +++ b/subgraphs/venus-governance/src/utilities/ids.ts @@ -3,7 +3,7 @@ import { Address, BigInt } from '@graphprotocol/graph-ts'; const SEPERATOR = '-'; export const getVoteId = (voter: Address, proposalId: BigInt): string => - [voter.toHexString(), proposalId.toHexString()].join(SEPERATOR); + [voter.toHexString(), proposalId.toString()].join(SEPERATOR); export const getPermissionId = ( accountAddress: Address, @@ -11,3 +11,5 @@ export const getPermissionId = ( functionSig: string, ): string => [accountAddress.toHexString(), contractAddress.toHexString(), functionSig].join(SEPERATOR); + +export const getDelegateId = (account: Address): string => account.toHexString(); diff --git a/subgraphs/venus-governance/subgraph-client/index.ts b/subgraphs/venus-governance/subgraph-client/index.ts index ee2bb4d9..04a43258 100644 --- a/subgraphs/venus-governance/subgraph-client/index.ts +++ b/subgraphs/venus-governance/subgraph-client/index.ts @@ -1,3 +1,4 @@ +import { DocumentNode } from 'graphql'; import { Client as UrqlClient, createClient } from 'urql/core'; import { @@ -18,28 +19,36 @@ class SubgraphClient { }); } + async query(document: DocumentNode, args: Record) { + const result = await this.urqlClient.query(document, args).toPromise(); + if (result.error) { + console.error(result.error); + } + return result; + } + async getProposalById(id: string) { - const result = await this.urqlClient.query(ProposalByIdDocument, { id: id }).toPromise(); + const result = await this.query(ProposalByIdDocument, { id: id }); return result; } async getDelegateById(id: string) { - const result = await this.urqlClient.query(DelegateByIdDocument, { id: id }).toPromise(); + const result = await this.query(DelegateByIdDocument, { id: id }); return result; } async getDelegates() { - const result = await this.urqlClient.query(DelegatesDocument, {}).toPromise(); + const result = await this.query(DelegatesDocument, {}); return result; } async getProposals() { - const result = await this.urqlClient.query(ProposalsDocument, {}).toPromise(); + const result = await this.query(ProposalsDocument, {}); return result; } async getPermissions() { - const result = await this.urqlClient.query(PermissionsDocument, {}).toPromise(); + const result = await this.query(PermissionsDocument, {}); return result; } } diff --git a/subgraphs/venus-governance/template.yaml b/subgraphs/venus-governance/template.yaml index 854cdd2f..030481e1 100644 --- a/subgraphs/venus-governance/template.yaml +++ b/subgraphs/venus-governance/template.yaml @@ -74,9 +74,9 @@ dataSources: name: GovernorBravoDelegate network: {{ network }} source: - address: "{{ governorBravoDelegateAddress }}" + address: "{{ governorBravoDelegatorAddress }}" abi: GovernorBravoDelegate - startBlock: {{ governorBravoDelegateStartBlock }} + startBlock: {{ governorBravoDelegatorStartBlock }} mapping: kind: ethereum/events apiVersion: 0.0.7 @@ -117,9 +117,9 @@ dataSources: name: GovernorBravoDelegate2 network: {{ network }} source: - address: "{{ governorBravoDelegateAddress }}" + address: "{{ governorBravoDelegatorAddress }}" abi: GovernorBravoDelegate2 - startBlock: {{ governorBravoDelegateStartBlock }} + startBlock: {{ governorBravoDelegatorStartBlock }} mapping: kind: ethereum/events apiVersion: 0.0.7 diff --git a/subgraphs/venus-governance/tests/common/mocks.ts b/subgraphs/venus-governance/tests/common/mocks.ts index be906743..e9508275 100644 --- a/subgraphs/venus-governance/tests/common/mocks.ts +++ b/subgraphs/venus-governance/tests/common/mocks.ts @@ -1,7 +1,7 @@ import { BigInt, ethereum } from '@graphprotocol/graph-ts'; import { createMockedFunction } from 'matchstick-as'; -import { governorBravoDelegateAddress } from '../../src/constants/addresses'; +import { governorBravoDelegatorAddress } from '../../src/constants/addresses'; import { mockAdminAddress, mockGuardianAddress, @@ -13,34 +13,34 @@ import { export const createGovernorBravoMocks = (): void => { createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'implementation', 'implementation():(address)', ).returns([ethereum.Value.fromAddress(mockImplementationAddress)]); - createMockedFunction(governorBravoDelegateAddress, 'admin', 'admin():(address)').returns([ + createMockedFunction(governorBravoDelegatorAddress, 'admin', 'admin():(address)').returns([ ethereum.Value.fromAddress(mockAdminAddress), ]); - createMockedFunction(governorBravoDelegateAddress, 'guardian', 'guardian():(address)').returns([ + createMockedFunction(governorBravoDelegatorAddress, 'guardian', 'guardian():(address)').returns([ ethereum.Value.fromAddress(mockGuardianAddress), ]); createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'quorumVotes', 'quorumVotes():(uint256)', ).returns([ethereum.Value.fromUnsignedBigInt(BigInt.fromString('0'))]); createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'proposalMaxOperations', 'proposalMaxOperations():(uint256)', ).returns([ethereum.Value.fromUnsignedBigInt(BigInt.fromString('0'))]); // Proposal Configs createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'proposalConfigs', 'proposalConfigs(uint256):(uint256,uint256,uint256)', ) @@ -51,7 +51,7 @@ export const createGovernorBravoMocks = (): void => { ethereum.Value.fromUnsignedBigInt(BigInt.fromString('300000000000000000000000')), ]); createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'proposalConfigs', 'proposalConfigs(uint256):(uint256,uint256,uint256)', ) @@ -62,7 +62,7 @@ export const createGovernorBravoMocks = (): void => { ethereum.Value.fromUnsignedBigInt(BigInt.fromString('300000000000000000000000')), ]); createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'proposalConfigs', 'proposalConfigs(uint256):(uint256,uint256,uint256)', ) @@ -74,21 +74,21 @@ export const createGovernorBravoMocks = (): void => { ]); createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'proposalTimelocks', 'proposalTimelocks(uint256):(address)', ) .withArgs([ethereum.Value.fromUnsignedBigInt(BigInt.fromString('0'))]) .returns([ethereum.Value.fromAddress(timelockAddress0)]); createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'proposalTimelocks', 'proposalTimelocks(uint256):(address)', ) .withArgs([ethereum.Value.fromUnsignedBigInt(BigInt.fromString('1'))]) .returns([ethereum.Value.fromAddress(timelockAddress1)]); createMockedFunction( - governorBravoDelegateAddress, + governorBravoDelegatorAddress, 'proposalTimelocks', 'proposalTimelocks(uint256):(address)', ) diff --git a/subgraphs/venus-governance/tests/integration/alpha.ts b/subgraphs/venus-governance/tests/integration/alpha.ts index 11e18614..0d0f5116 100644 --- a/subgraphs/venus-governance/tests/integration/alpha.ts +++ b/subgraphs/venus-governance/tests/integration/alpha.ts @@ -14,14 +14,19 @@ describe('GovernorAlpha', function () { let signers: SignerWithAddress[]; let governorAlpha: Contract; let governorAlpha2: Contract; + let _: SignerWithAddress; + let user1: SignerWithAddress; + let user2: SignerWithAddress; + let user3: SignerWithAddress; + let user4: SignerWithAddress; before(async function () { - this.timeout(50000000); // sometimes it takes a long time + this.timeout(10000000); // sometimes it takes a long time governorAlpha = await ethers.getContract('GovernorAlpha'); governorAlpha2 = await ethers.getContract('GovernorAlpha2'); signers = await ethers.getSigners(); - const [_, user1, user2, user3, user4] = signers; + [_, user1, user2, user3, user4] = signers; await enfranchiseAccount(user1, scaleValue(100000, 18)); await enfranchiseAccount(user2, scaleValue(200000, 18)); @@ -53,8 +58,7 @@ describe('GovernorAlpha', function () { } = await subgraphClient.getProposalById('1'); expect(proposal.id).to.be.equal('1'); expect(proposal.description).to.be.equal('Test proposal 1'); - expect(proposal.status).to.be.equal('PENDING'); - expect(proposal.executionETA).to.be.null; + expect(proposal.executionEta).to.be.null; expect(proposal.targets).to.deep.equal([ '0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396'.toLowerCase(), ]); @@ -66,18 +70,12 @@ describe('GovernorAlpha', function () { it('index for vote cast', async function () { const [_, user1, user2, user3, user4] = signers; - const time = Date.now() + 106400; - await ethers.provider.send('evm_setNextBlockTimestamp', [time]); await mine(1); - let tx = await governorAlpha.connect(user1).castVote('1', false); - await tx.wait(1); - tx = await governorAlpha.connect(user2).castVote('1', true); - await tx.wait(1); - tx = await governorAlpha.connect(user3).castVote('1', true); - await tx.wait(1); - tx = await governorAlpha.connect(user4).castVote('1', true); - await tx.wait(1); + await governorAlpha.connect(user1).castVote('1', false); + await governorAlpha.connect(user2).castVote('1', true); + await governorAlpha.connect(user3).castVote('1', true); + await governorAlpha.connect(user4).castVote('1', true); await waitForSubgraphToBeSynced(SYNC_DELAY); @@ -90,7 +88,7 @@ describe('GovernorAlpha', function () { data: { delegate: delegate1 }, } = await subgraphClient.getDelegateById(user1.address.toLowerCase()); - expect(delegate1.votes[0].id).to.equal(`${user1.address.toLowerCase()}-0x1`); + expect(delegate1.votes[0].id).to.equal(`${user1.address.toLowerCase()}-1`); expect(delegate1.votes[0].support).to.equal('AGAINST'); expect(delegate1.votes[0].votes).to.equal('100000000000000000000000'); expect(delegate1.proposals).to.deep.equal([]); @@ -98,24 +96,34 @@ describe('GovernorAlpha', function () { const { data: { delegate: delegate2 }, } = await subgraphClient.getDelegateById(user2.address.toLowerCase()); - expect(delegate2.votes[0].id).to.equal(`${user2.address.toLowerCase()}-0x1`); + expect(delegate2.votes[0].id).to.equal(`${user2.address.toLowerCase()}-1`); expect(delegate2.votes[0].support).to.equal('FOR'); expect(delegate2.votes[0].votes).to.equal('200000000000000000000000'); expect(delegate2.proposals).to.deep.equal([]); - expect(delegate2.proposals).to.deep.equal([]); const { data: { delegate: delegate4 }, } = await subgraphClient.getDelegateById(user4.address.toLowerCase()); expect(delegate4.proposals).to.deep.equal([{ id: '1', __typename: 'Proposal' }]); }); - }); - // @TODO Update proposal Status - // @TODO Changing delegates - // @TODO Governance + it('should transition to canceled', async () => { + await governorAlpha.connect(signers[0]).cancel('1'); + + await waitForSubgraphToBeSynced(SYNC_DELAY); + + const { + data: { proposal }, + } = await subgraphClient.getProposalById('1'); + + expect(proposal.canceled).to.equal(true); + }); + }); describe('Alpha2', function () { + before(async function () { + this.timeout(10000000); // sometimes it takes a long time + }); it('indexes created proposals - alpha2', async function () { const [_, user1] = signers; await enfranchiseAccount(user1, scaleValue(600000, 18)); @@ -130,8 +138,13 @@ describe('GovernorAlpha', function () { 'Test proposal 21', // description ]; - const tx = await governorAlpha2.connect(user1).propose(...vip); - await tx.wait(1); + await governorAlpha2.connect(user1).propose(...vip); + + await mine(1); + + // Voting so it passes + await governorAlpha2.connect(user4).castVote('21', true); + await governorAlpha2.connect(user3).castVote('21', true); await waitForSubgraphToBeSynced(SYNC_DELAY); @@ -141,8 +154,7 @@ describe('GovernorAlpha', function () { expect(proposal.id).to.be.equal('21'); expect(proposal.description).to.be.equal('Test proposal 21'); - expect(proposal.status).to.be.equal('PENDING'); - expect(proposal.executionETA).to.be.null; + expect(proposal.executionEta).to.be.null; expect(proposal.targets).to.deep.equal([ '0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396'.toLowerCase(), ]); @@ -150,5 +162,44 @@ describe('GovernorAlpha', function () { expect(proposal.signatures).to.deep.equal(['setPendingAdmin(address)']); expect(proposal.calldatas).to.deep.equal([callData]); }); + + it('should transition to queued', async () => { + let votingPeriod = +(await governorAlpha2.votingPeriod()); + while (votingPeriod > 0) { + votingPeriod--; + await mine(1); + } + await waitForSubgraphToBeSynced(SYNC_DELAY); + + await governorAlpha2.queue(21); + + const governorAlpha2Timelock = await ethers.getContract('GovernorAlpha2Timelock'); + const eta = + (await ethers.provider.getBlock(await ethers.provider.getBlockNumber())).timestamp + + +(await governorAlpha2Timelock.delay()); + + await waitForSubgraphToBeSynced(SYNC_DELAY); + + const { + data: { proposal }, + } = await subgraphClient.getProposalById('21'); + + expect(proposal.queued).to.equal(true); + expect(proposal.executionEta).to.equal(eta.toString()); + + await ethers.provider.send('evm_setNextBlockTimestamp', [eta + 1]); + }); + + it('should transition to executed', async () => { + await governorAlpha2.execute('21'); + + await waitForSubgraphToBeSynced(SYNC_DELAY); + + const { + data: { proposal }, + } = await subgraphClient.getProposalById('21'); + + expect(proposal.executed).to.equal(true); + }); }); }); diff --git a/subgraphs/venus-governance/tests/integration/queries/proposalByIdQuery.graphql b/subgraphs/venus-governance/tests/integration/queries/proposalByIdQuery.graphql index 7442d9de..61e98f37 100644 --- a/subgraphs/venus-governance/tests/integration/queries/proposalByIdQuery.graphql +++ b/subgraphs/venus-governance/tests/integration/queries/proposalByIdQuery.graphql @@ -11,8 +11,10 @@ query ProposalById($id: ID!) { startBlock endBlock description - status - executionETA + executionEta + queued + canceled + executed votes { id votes diff --git a/subgraphs/venus-governance/tests/integration/queries/proposalsQuery.graphql b/subgraphs/venus-governance/tests/integration/queries/proposalsQuery.graphql index 83f362e7..78f26d30 100644 --- a/subgraphs/venus-governance/tests/integration/queries/proposalsQuery.graphql +++ b/subgraphs/venus-governance/tests/integration/queries/proposalsQuery.graphql @@ -11,8 +11,10 @@ query Proposals { startBlock endBlock description - status - executionETA + executionEta + queued + canceled + executed votes { id votes diff --git a/subgraphs/venus-governance/tests/integration/utils/constants.ts b/subgraphs/venus-governance/tests/integration/utils/constants.ts index 4ce9aad5..972629ab 100644 --- a/subgraphs/venus-governance/tests/integration/utils/constants.ts +++ b/subgraphs/venus-governance/tests/integration/utils/constants.ts @@ -3,3 +3,5 @@ export const SUBGRAPH_ACCOUNT = 'venusprotocol'; export const SUBGRAPH_NAME = 'venus-governance'; export const SYNC_DELAY = 2000; + +export const mockAddress = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'; diff --git a/subgraphs/venus-governance/tests/integration/utils/fixtures.ts b/subgraphs/venus-governance/tests/integration/utils/fixtures.ts deleted file mode 100644 index 0fe9047c..00000000 --- a/subgraphs/venus-governance/tests/integration/utils/fixtures.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { ethers } from 'hardhat'; - -const xvsVaultFixture = async () => { - const xvs = await ethers.getContract('XVS'); - const xvsVault = await ethers.getContract('XVSVault'); - const xvsVaultProxy = await ethers.getContract('XVSVaultProxy'); - const xvsStore = await ethers.getContract('XVSStore'); - const timelock = await ethers.getContract('Timelock'); - - // approve xvs spending to xvs vault - const approvalAmount = ethers.BigNumber.from(ethers.BigNumber.from(10).pow(10)) - .mul(ethers.BigNumber.from(10).pow(18)) - .toString(); - await xvs.approve(xvsVault.address, approvalAmount); - - // deposit xvs to xvs vault - const amount = ethers.BigNumber.from(ethers.BigNumber.from(7).pow(5)) - .mul(ethers.BigNumber.from(10).pow(18)) - .toString(); - await xvsVault.deposit(xvs.address, 0, amount); - return { - xvsVault, - xvsVaultProxy, - xvs, - xvsStore, - timelock, - }; -}; - -const governorFixture = async () => { - const governorAlpha = await ethers.getContract('GovernorAlpha'); - - const governorAlpha2 = await ethers.getContract('GovernorAlpha2'); - - return { - governorAlpha, - governorAlpha2, - }; -}; - -async function deploy() { - const { timelock, xvsVault, xvs } = await xvsVaultFixture(); - const { governorAlpha, governorAlpha2 } = await governorFixture(); - return { - governorAlpha, - governorAlpha2, - timelock, - xvs, - xvsVault, - }; -} - -export default deploy; diff --git a/subgraphs/venus-governance/tests/integration/utils/voter.ts b/subgraphs/venus-governance/tests/integration/utils/voter.ts index 199f3662..193557bf 100644 --- a/subgraphs/venus-governance/tests/integration/utils/voter.ts +++ b/subgraphs/venus-governance/tests/integration/utils/voter.ts @@ -3,7 +3,8 @@ import { ethers } from 'hardhat'; export async function enfranchiseAccount(account: any, amount: BigNumber) { const xvs = await ethers.getContract('XVS'); - const xvsVault = await ethers.getContract('XVSVault'); + const xvsVaultProxy = await ethers.getContract('XVSVaultProxy'); + const xvsVault = await ethers.getContractAt('XVSVault', xvsVaultProxy.address); await xvs.connect(account).approve(xvsVault.address, amount.toFixed()); diff --git a/subgraphs/venus-governance/tests/integration/xvsVault.ts b/subgraphs/venus-governance/tests/integration/xvsVault.ts index c8f9f05e..ff7169da 100644 --- a/subgraphs/venus-governance/tests/integration/xvsVault.ts +++ b/subgraphs/venus-governance/tests/integration/xvsVault.ts @@ -20,7 +20,8 @@ describe('XVS Vault and Delegation', function () { signers = await ethers.getSigners(); xvs = await ethers.getContract('XVS'); - xvsVault = await ethers.getContract('XVSVault'); + const xvsVaultProxy = await ethers.getContract('XVSVaultProxy'); + xvsVault = await ethers.getContractAt('XVSVault', xvsVaultProxy.address); await waitForSubgraphToBeSynced(SYNC_DELAY); }); diff --git a/subgraphs/venus-governance/tests/unit/Alpha/index.test.ts b/subgraphs/venus-governance/tests/unit/Alpha/index.test.ts index 73c40605..2e4994d8 100644 --- a/subgraphs/venus-governance/tests/unit/Alpha/index.test.ts +++ b/subgraphs/venus-governance/tests/unit/Alpha/index.test.ts @@ -16,7 +16,6 @@ import { ProposalQueued, } from '../../../generated/GovernorAlpha/GovernorAlpha'; import { Delegate } from '../../../generated/schema'; -import { governorBravoDelegateAddress } from '../../../src/constants/addresses'; import { handleProposalCanceled, handleProposalCreated, @@ -49,7 +48,7 @@ beforeAll(() => { }); beforeEach(() => { - getOrCreateDelegate(user1.toHexString()); + getOrCreateDelegate(user1); const proposalCreatedEvent = createProposalCreatedEvent( 1, user1, @@ -107,7 +106,7 @@ describe('Alpha', () => { const assertProposalDocument = (key: string, value: string): void => { assert.fieldEquals('Proposal', '1', key, value); }; - assertProposalDocument('status', 'CANCELLED'); + assertProposalDocument('canceled', 'true'); }); test('queue proposal', () => { @@ -121,13 +120,8 @@ describe('Alpha', () => { assert.fieldEquals('Proposal', '1', key, value); }; - const assertGovernanceDocument = (key: string, value: string): void => { - assert.fieldEquals('Governance', governorBravoDelegateAddress.toHex(), key, value); - }; - - assertProposalDocument('status', 'QUEUED'); - assertProposalDocument('executionETA', eta.toString()); - assertGovernanceDocument('proposalsQueued', '1'); + assertProposalDocument('queued', 'true'); + assertProposalDocument('executionEta', eta.toString()); }); test('proposal executed', () => { @@ -144,13 +138,7 @@ describe('Alpha', () => { assert.fieldEquals('Proposal', '1', key, value); }; - const assertGovernanceDocument = (key: string, value: string): void => { - assert.fieldEquals('Governance', governorBravoDelegateAddress.toHex(), key, value); - }; - - assertProposalDocument('status', 'EXECUTED'); - assertProposalDocument('executionETA', 'null'); - assertGovernanceDocument('proposalsQueued', '0'); + assertProposalDocument('executed', 'true'); }); test('vote cast', () => { diff --git a/subgraphs/venus-governance/tests/unit/Bravo/index.test.ts b/subgraphs/venus-governance/tests/unit/Bravo/index.test.ts index 879d5c49..a49681ea 100644 --- a/subgraphs/venus-governance/tests/unit/Bravo/index.test.ts +++ b/subgraphs/venus-governance/tests/unit/Bravo/index.test.ts @@ -17,7 +17,7 @@ import { ProposalQueued, } from '../../../generated/GovernorBravoDelegate/GovernorBravoDelegate'; import { Delegate } from '../../../generated/schema'; -import { governorBravoDelegateAddress } from '../../../src/constants/addresses'; +import { governorBravoDelegatorAddress } from '../../../src/constants/addresses'; import { handleBravoVoteCast, handleNewAdmin, @@ -66,7 +66,7 @@ beforeAll(() => { beforeEach(() => { /** setup test */ - getOrCreateDelegate(user1.toHexString()); + getOrCreateDelegate(user1); const proposalCreatedEvent = createProposalCreatedEvent( 1, user1, @@ -128,7 +128,6 @@ describe('Bravo', () => { assertProposalDocument('startBlock', `${startBlock}`); assertProposalDocument('endBlock', `${endBlock}`); assertProposalDocument('description', description); - assertProposalDocument('status', 'PENDING'); }); test('create proposal V2', () => { @@ -174,7 +173,6 @@ describe('Bravo', () => { assertProposalDocument('startBlock', `${startBlock}`); assertProposalDocument('endBlock', `${endBlock}`); assertProposalDocument('description', description); - assertProposalDocument('status', 'PENDING'); assertProposalDocument('type', 'CRITICAL'); }); @@ -203,7 +201,7 @@ describe('Bravo', () => { const assertProposalDocument = (key: string, value: string): void => { assert.fieldEquals('Proposal', '1', key, value); }; - assertProposalDocument('status', 'CANCELLED'); + assertProposalDocument('canceled', 'true'); }); test('queue proposal', () => { @@ -217,13 +215,8 @@ describe('Bravo', () => { assert.fieldEquals('Proposal', '1', key, value); }; - const assertGovernanceDocument = (key: string, value: string): void => { - assert.fieldEquals('Governance', governorBravoDelegateAddress.toHex(), key, value); - }; - - assertProposalDocument('status', 'QUEUED'); - assertProposalDocument('executionETA', eta.toString()); - assertGovernanceDocument('proposalsQueued', '1'); + assertProposalDocument('queued', 'true'); + assertProposalDocument('executionEta', eta.toString()); }); test('proposal executed', () => { @@ -240,13 +233,7 @@ describe('Bravo', () => { assert.fieldEquals('Proposal', '1', key, value); }; - const assertGovernanceDocument = (key: string, value: string): void => { - assert.fieldEquals('Governance', governorBravoDelegateAddress.toHex(), key, value); - }; - - assertProposalDocument('status', 'EXECUTED'); - assertProposalDocument('executionETA', 'null'); - assertGovernanceDocument('proposalsQueued', '0'); + assertProposalDocument('executed', 'true'); }); test('vote cast', () => { @@ -282,7 +269,7 @@ describe('Bravo', () => { handleNewImplementation(newImplementationEvent); assert.fieldEquals( 'Governance', - governorBravoDelegateAddress.toHex(), + governorBravoDelegatorAddress.toHex(), 'implementation', newImplementation.toHexString(), ); @@ -300,7 +287,7 @@ describe('Bravo', () => { handleNewPendingAdmin(pendingAdminEvent); assert.fieldEquals( 'Governance', - governorBravoDelegateAddress.toHex(), + governorBravoDelegatorAddress.toHex(), 'pendingAdmin', newPendingAdmin.toHexString(), ); @@ -314,11 +301,11 @@ describe('Bravo', () => { handleNewAdmin(newAdminEvent); assert.fieldEquals( 'Governance', - governorBravoDelegateAddress.toHex(), + governorBravoDelegatorAddress.toHex(), 'admin', newAdmin.toHexString(), ); - assert.fieldEquals('Governance', governorBravoDelegateAddress.toHex(), 'pendingAdmin', 'null'); + assert.fieldEquals('Governance', governorBravoDelegatorAddress.toHex(), 'pendingAdmin', 'null'); }); test('registers new guardian', () => { @@ -329,7 +316,7 @@ describe('Bravo', () => { handleNewGuardian(newGuardianEvent); assert.fieldEquals( 'Governance', - governorBravoDelegateAddress.toHex(), + governorBravoDelegatorAddress.toHex(), 'guardian', newGuardian.toHexString(), ); @@ -347,7 +334,7 @@ describe('Bravo', () => { handleProposalMaxOperationsUpdated(newProposalMaxOperationsEvent); assert.fieldEquals( 'Governance', - governorBravoDelegateAddress.toHex(), + governorBravoDelegatorAddress.toHex(), 'proposalMaxOperations', newProposalMaxOperations.toString(), ); diff --git a/subgraphs/venus-governance/tests/unit/XVSVault/index.test.ts b/subgraphs/venus-governance/tests/unit/XVSVault/index.test.ts index 52e6d689..e0e4c8de 100644 --- a/subgraphs/venus-governance/tests/unit/XVSVault/index.test.ts +++ b/subgraphs/venus-governance/tests/unit/XVSVault/index.test.ts @@ -25,7 +25,7 @@ beforeAll(() => { beforeEach(() => { /** setup test */ - getOrCreateDelegate(user1.toHexString()); + getOrCreateDelegate(user1); const proposalCreatedEvent = createProposalCreatedEvent( 1, user1, diff --git a/tsconfig.json b/tsconfig.json index d5c0261a..b17a342e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,8 @@ "noLib": false, "lib": ["es2015"], "forceConsistentCasingInFileNames": true, - "esModuleInterop": true + "esModuleInterop": true, + "resolveJsonModule": true }, "include": ["subgraphs", "hardhat.config.ts"] }