Skip to content

Commit

Permalink
feat: add account management methods to GRE (#645)
Browse files Browse the repository at this point in the history
* feat: add account management methods to GRE

Signed-off-by: Tomás Migone <tomas@edgeandnode.com>
  • Loading branch information
tmigone authored Jul 28, 2022
1 parent 7c6e27d commit 842a8da
Show file tree
Hide file tree
Showing 32 changed files with 388 additions and 152 deletions.
36 changes: 30 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,34 +90,58 @@ To test a single file run: `npx hardhat test test/<FILE_NAME>.ts`

## E2E Testing

End to end tests are also available and can be run against a local network or a live network. These can be useful to validate a protocol deployment is configured and working as expected.
End to end tests are also available and can be run against a local network or a live network. These can be useful to validate a protocol deployment is configured and working as expected.

There are several types of e2e tests which can be run separately:
- **deployment/config**
- Test the configuration of deployed contracts (parameters that don't change over time).
- Can be run against any network at any time and the tests should pass.
- Only read only interactions with the blockchain.
- Example: a test validating the curation default reserve ratio matches the value in the graph config file.
- **deployment/init**
- Test the initialization of deployed contracts (parameters that change with protocol usage).
- Can be run against a "fresh" protocol deployment. Running these tests against a protocol with pre-existing state will probably fail.
- Only read only interactions with the blockchain.
- Example: a test validating that the GRT total supply equals 10B, this is only true on a freshly deployed protocol until the first allocation is closed and protocol issuance kicks in.
- **scenarios**
- Test the execution of common protocol actions.
- Can be run against any network at any time and the tests should pass.
- Read and write interactions with the blockchain. _Requires an account with sufficient balance!_
- Example: a test validating that a user can add signal to a subgraph.

### Hardhat local node

To run e2e tests against a hardhat local node run:
To run all e2e tests against a hardhat local node run:

```bash
yarn test:e2e
```

The command will invoke several hardhat tasks, including:
The command will perform the following actions:

- Start a hardhat node (localhost)
- Run `migrate:accounts` hardhat task to create keys for all protocol roles (deployer, governor, arbiter, etc). This currently doesn't support multisig accounts.
- Run `migrate` hardhat task to deploy the protocol
- Run `migrate:ownership` hardhat task to transfer ownership of governed contracts to the governor
- Run `migrate:unpause` to unpause the protocol
- Run e2e tests
- Run `e2e` hardhat task to run all e2e tests

### Other networks

To run tests against a live testnet or even mainnet run:

```bash
GRAPH_CONFIG=config/graph.<network>.yml ADDRESS_BOOK=addresses.json npx hardhat test e2e/**/*.ts --network <network>
# All e2e tests
npx hardhat e2e --network <network> --graph-config config/graph.<network>.yml

# Only deployment config tests
npx hardhat e2e:config --network <network> --graph-config config/graph.<network>.yml

# Only deployment init tests
npx hardhat e2e:init --network <network> --graph-config config/graph.<network>.yml
```

This command will only run the tests so you need to be sure the protocol is already deployed and the graph config file and address book files are up to date.
Note that this command will only run the tests so you need to be sure the protocol is already deployed and the graph config file and address book files are up to date.

# Interacting with the contracts

Expand Down
16 changes: 16 additions & 0 deletions config/graph.goerli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ contracts:
- fn: "setContractProxy"
id: "0x45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247" # keccak256('GraphToken')
contractAddress: "${{GraphToken.address}}"
- fn: "setPauseGuardian"
pauseGuardian: *pauseGuardian
- fn: "transferOwnership"
owner: *governor
GraphProxyAdmin:
calls:
- fn: "transferOwnership"
owner: *governor
ServiceRegistry:
proxy: true
init:
Expand All @@ -45,6 +53,9 @@ contracts:
calls:
- fn: "addMinter"
minter: "${{RewardsManager.address}}"
- fn: "renounceMinter"
- fn: "transferOwnership"
owner: *governor
Curation:
proxy: true
init:
Expand Down Expand Up @@ -79,6 +90,8 @@ contracts:
tokenDescriptor: "${{SubgraphNFTDescriptor.address}}"
- fn: "setMinter"
minter: "${{GNS.address}}"
- fn: "transferOwnership"
owner: *governor
Staking:
proxy: true
init:
Expand Down Expand Up @@ -107,6 +120,9 @@ contracts:
init:
controller: "${{Controller.address}}"
issuanceRate: "1000000012184945188" # per block increase of total supply, blocks in a year = 365*60*60*24/13
calls:
- fn: "setSubgraphAvailabilityOracle"
subgraphAvailabilityOracle: *availabilityOracle
AllocationExchange:
init:
graphToken: "${{GraphToken.address}}"
Expand Down
31 changes: 0 additions & 31 deletions e2e/deployment/allocationExchange.test.ts

This file was deleted.

30 changes: 30 additions & 0 deletions e2e/deployment/config/allocationExchange.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { NamedAccounts } from '../../../tasks/type-extensions'

describe('AllocationExchange configuration', () => {
const {
contracts: { AllocationExchange },
getNamedAccounts,
} = hre.graph()

let namedAccounts: NamedAccounts

before(async () => {
namedAccounts = await getNamedAccounts()
})

it('should be owned by allocationExchangeOwner', async function () {
const owner = await AllocationExchange.governor()
expect(owner).eq(namedAccounts.allocationExchangeOwner.address)
})

it('should accept vouchers from authority', async function () {
const allowed = await AllocationExchange.authority(namedAccounts.authority.address)
expect(allowed).eq(true)
})

// graphToken and staking are private variables so we can't verify
it.skip('graphToken should match the GraphToken deployment address')
it.skip('staking should match the Staking deployment address')
})
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect } from 'chai'
import hre, { ethers } from 'hardhat'
import { getItemValue } from '../../cli/config'
import { NamedAccounts } from '../../../tasks/type-extensions'

describe('Controller deployment', () => {
const { contracts, graphConfig } = hre.graph()
describe('Controller configuration', () => {
const { contracts, getNamedAccounts } = hre.graph()
const { Controller } = contracts

const proxyContracts = [
Expand All @@ -16,6 +16,12 @@ describe('Controller deployment', () => {
'GraphToken',
]

let namedAccounts: NamedAccounts

before(async () => {
namedAccounts = await getNamedAccounts()
})

const proxyShouldMatchDeployed = async (contractName: string) => {
const curationAddress = await Controller.getContractProxy(
ethers.utils.solidityKeccak256(['string'], [contractName]),
Expand All @@ -25,14 +31,12 @@ describe('Controller deployment', () => {

it('should be owned by governor', async function () {
const owner = await Controller.governor()
const governorAddress = getItemValue(graphConfig, 'general/governor')
expect(owner).eq(governorAddress)
expect(owner).eq(namedAccounts.governor.address)
})

it('pause guardian should be able to pause protocol', async function () {
const pauseGuardianAddress = getItemValue(graphConfig, 'general/pauseGuardian')
const pauseGuardian = await Controller.pauseGuardian()
expect(pauseGuardian).eq(pauseGuardianAddress)
expect(pauseGuardian).eq(namedAccounts.pauseGuardian.address)
})

describe('proxy contract', async function () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { getItemValue } from '../../cli/config'
import { getItemValue } from '../../../cli/config'

describe('Curation deployment', () => {
describe('Curation configuration', () => {
const {
graphConfig,
contracts: { Controller, Curation, BancorFormula, GraphCurationToken },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { getItemValue } from '../../cli/config'
import { getItemValue } from '../../../cli/config'

describe('DisputeManager deployment', () => {
describe('DisputeManager configuration', () => {
const {
graphConfig,
contracts: { Controller, DisputeManager },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { getItemValue } from '../../cli/config'
import { getItemValue } from '../../../cli/config'

describe('EpochManager deployment', () => {
describe('EpochManager configuration', () => {
const {
graphConfig,
contracts: { EpochManager, Controller },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect } from 'chai'
import hre from 'hardhat'

describe('GNS deployment', () => {
describe('GNS configuration', () => {
const {
contracts: { Controller, GNS, BancorFormula, SubgraphNFT, GraphToken, Curation },
contracts: { Controller, GNS, BancorFormula, SubgraphNFT },
} = hre.graph()

it('should be controlled by Controller', async function () {
Expand All @@ -20,9 +20,4 @@ describe('GNS deployment', () => {
const subgraphNFT = await GNS.subgraphNFT()
expect(subgraphNFT).eq(SubgraphNFT.address)
})

it('should allow Curation contract to spend MAX_UINT256 tokens on GNS behalf', async function () {
const allowance = await GraphToken.allowance(GNS.address, Curation.address)
expect(allowance).eq(hre.ethers.constants.MaxUint256)
})
})
21 changes: 21 additions & 0 deletions e2e/deployment/config/graphProxyAdmin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { NamedAccounts } from '../../../tasks/type-extensions'

describe('GraphProxyAdmin configuration', () => {
const {
contracts: { GraphProxyAdmin },
getNamedAccounts,
} = hre.graph()

let namedAccounts: NamedAccounts

before(async () => {
namedAccounts = await getNamedAccounts()
})

it('should be owned by governor', async function () {
const owner = await GraphProxyAdmin.governor()
expect(owner).eq(namedAccounts.governor.address)
})
})
33 changes: 33 additions & 0 deletions e2e/deployment/config/graphToken.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { NamedAccounts } from '../../../tasks/type-extensions'

describe('GraphToken configuration', () => {
const {
getNamedAccounts,
contracts: { GraphToken, RewardsManager },
getDeployer,
} = hre.graph()

let namedAccounts: NamedAccounts

before(async () => {
namedAccounts = await getNamedAccounts()
})

it('should be owned by governor', async function () {
const owner = await GraphToken.governor()
expect(owner).eq(namedAccounts.governor.address)
})

it('deployer should not be minter', async function () {
const deployer = await getDeployer()
const deployerIsMinter = await GraphToken.isMinter(deployer.address)
hre.network.config.chainId === 1337 ? this.skip() : expect(deployerIsMinter).eq(false)
})

it('RewardsManager should be minter', async function () {
const deployerIsMinter = await GraphToken.isMinter(RewardsManager.address)
expect(deployerIsMinter).eq(true)
})
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from 'chai'
import hre from 'hardhat'

describe('Protocol', () => {
describe('Protocol configuration', () => {
const { contracts } = hre.graph()

it('should be unpaused', async function () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { getItemValue } from '../../cli/config'
import { getItemValue } from '../../../cli/config'
import { NamedAccounts } from '../../../tasks/type-extensions'

describe('RewardsManager deployment', () => {
describe('RewardsManager configuration', () => {
const {
graphConfig,
getNamedAccounts,
contracts: { RewardsManager, Controller },
} = hre.graph()

let namedAccounts: NamedAccounts

before(async () => {
namedAccounts = await getNamedAccounts()
})

it('should be controlled by Controller', async function () {
const controller = await RewardsManager.controller()
expect(controller).eq(Controller.address)
Expand All @@ -20,8 +28,7 @@ describe('RewardsManager deployment', () => {
})

it('should allow subgraph availability oracle to deny rewards', async function () {
const availabilityOracleAddress = getItemValue(graphConfig, 'general/availabilityOracle')
const availabilityOracle = await RewardsManager.subgraphAvailabilityOracle()
expect(availabilityOracle).eq(availabilityOracleAddress)
expect(availabilityOracle).eq(namedAccounts.availabilityOracle.address)
})
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from 'chai'
import hre from 'hardhat'

describe('ServiceRegistry deployment', () => {
describe('ServiceRegistry configuration', () => {
const {
contracts: { ServiceRegistry, Controller },
} = hre.graph()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { expect } from 'chai'
import hre from 'hardhat'
import { getItemValue } from '../../cli/config'
import { getItemValue } from '../../../cli/config'

describe('Staking deployment', () => {
describe('Staking configuration', () => {
const {
graphConfig,
contracts: { Staking, Controller, DisputeManager, AllocationExchange },
Expand Down
Loading

0 comments on commit 842a8da

Please sign in to comment.