Skip to content

Commit 07c0790

Browse files
authored
Sync: l2-testnet / scenario1 > dev (#703)
* chore: sync changes from l2 branches Signed-off-by: Tomás Migone <[email protected]>
1 parent 69dcc9a commit 07c0790

27 files changed

+899
-263
lines changed

TESTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ The command will perform the following actions:
4848
- Run `migrate` hardhat task to deploy the protocol
4949
- Run `migrate:ownership` hardhat task to transfer ownership of governed contracts to the governor
5050
- Run `migrate:unpause` to unpause the protocol
51-
- Run `e2e` hardhat task to run all e2e tests, including scenarios
51+
- Run `e2e` hardhat task to run all deployment tests (config and init)
52+
- Run `e2e:scenario` hardhat task to run a scenario
5253

5354
### Other networks
5455

cli/commands/migrate.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ const allContracts = [
3535
'AllocationExchange',
3636
]
3737

38-
export const migrate = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise<void> => {
38+
export const migrate = async (
39+
cli: CLIEnvironment,
40+
cliArgs: CLIArgs,
41+
autoMine = false,
42+
): Promise<void> => {
3943
const graphConfigPath = cliArgs.graphConfig
4044
const force = cliArgs.force
4145
const contractName = cliArgs.contract
@@ -140,7 +144,7 @@ export const migrate = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise<vo
140144
logger.info(`Sent ${nTx} transaction${nTx === 1 ? '' : 's'} & spent ${EtherSymbol} ${spent}`)
141145

142146
if (chainId == 1337) {
143-
await (cli.wallet.provider as providers.JsonRpcProvider).send('evm_setAutomine', [false])
147+
await (cli.wallet.provider as providers.JsonRpcProvider).send('evm_setAutomine', [autoMine])
144148
}
145149
}
146150

config/graph.mainnet.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ contracts:
3030
- fn: "setContractProxy"
3131
id: "0x45fc200c7e4544e457d3c5709bfe0d520442c30bbcbdaede89e8d4a4bbc19247" # keccak256('GraphToken')
3232
contractAddress: "${{GraphToken.address}}"
33+
- fn: "setPauseGuardian"
34+
pauseGuardian: *pauseGuardian
35+
- fn: "transferOwnership"
36+
owner: *governor
37+
GraphProxyAdmin:
38+
calls:
39+
- fn: "transferOwnership"
40+
owner: *governor
3341
ServiceRegistry:
3442
proxy: true
3543
init:
@@ -45,6 +53,9 @@ contracts:
4553
calls:
4654
- fn: "addMinter"
4755
minter: "${{RewardsManager.address}}"
56+
- fn: "renounceMinter"
57+
- fn: "transferOwnership"
58+
owner: *governor
4859
Curation:
4960
proxy: true
5061
init:
@@ -79,6 +90,8 @@ contracts:
7990
tokenDescriptor: "${{SubgraphNFTDescriptor.address}}"
8091
- fn: "setMinter"
8192
minter: "${{GNS.address}}"
93+
- fn: "transferOwnership"
94+
owner: *governor
8295
Staking:
8396
proxy: true
8497
init:
@@ -109,11 +122,13 @@ contracts:
109122
calls:
110123
- fn: "setIssuanceRate"
111124
issuanceRate: "1000000012184945188" # per block increase of total supply, blocks in a year = 365*60*60*24/13
125+
- fn: "setSubgraphAvailabilityOracle"
126+
subgraphAvailabilityOracle: *availabilityOracle
112127
AllocationExchange:
113128
init:
114129
graphToken: "${{GraphToken.address}}"
115130
staking: "${{Staking.address}}"
116-
governor: *governor
131+
governor: *allocationExchangeOwner
117132
authority: *authority
118133
calls:
119134
- fn: "approveAll"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { expect } from 'chai'
2+
import hre from 'hardhat'
3+
import { AllocationFixture, getIndexerFixtures, IndexerFixture } from './fixtures/indexers'
4+
5+
enum AllocationState {
6+
Null,
7+
Active,
8+
Closed,
9+
Finalized,
10+
Claimed,
11+
}
12+
13+
let indexerFixtures: IndexerFixture[]
14+
15+
describe('Close allocations', () => {
16+
const { contracts, getTestAccounts } = hre.graph()
17+
const { Staking } = contracts
18+
19+
before(async () => {
20+
indexerFixtures = getIndexerFixtures(await getTestAccounts())
21+
})
22+
23+
describe('Allocations', () => {
24+
let allocations: AllocationFixture[] = []
25+
let openAllocations: AllocationFixture[] = []
26+
let closedAllocations: AllocationFixture[] = []
27+
28+
before(async () => {
29+
allocations = indexerFixtures.map((i) => i.allocations).flat()
30+
openAllocations = allocations.filter((a) => !a.close)
31+
closedAllocations = allocations.filter((a) => a.close)
32+
})
33+
34+
it(`some allocatons should be open`, async function () {
35+
for (const allocation of openAllocations) {
36+
const state = await Staking.getAllocationState(allocation.signer.address)
37+
expect(state).eq(AllocationState.Active)
38+
}
39+
})
40+
41+
it(`some allocatons should be closed`, async function () {
42+
for (const allocation of closedAllocations) {
43+
const state = await Staking.getAllocationState(allocation.signer.address)
44+
expect(state).eq(AllocationState.Closed)
45+
}
46+
})
47+
})
48+
})

e2e/scenarios/close-allocations.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// ### Scenario description ###
2+
// Common protocol actions > Close some allocations
3+
// This scenario will close several open allocations. See fixtures for details.
4+
// Need to wait at least 1 epoch after the allocations have been created before running it.
5+
// On localhost, the epoch is automatically advanced to guarantee this.
6+
// Run with:
7+
// npx hardhat e2e:scenario close-allocations --network <network> --graph-config config/graph.<network>.yml
8+
9+
import hre from 'hardhat'
10+
import { closeAllocation } from './lib/staking'
11+
import { advanceToNextEpoch } from '../../test/lib/testHelpers'
12+
import { fundAccountsETH } from './lib/accounts'
13+
import { getIndexerFixtures } from './fixtures/indexers'
14+
import { getGraphOptsFromArgv } from './lib/helpers'
15+
16+
async function main() {
17+
const graphOpts = getGraphOptsFromArgv()
18+
const graph = hre.graph(graphOpts)
19+
const indexerFixtures = getIndexerFixtures(await graph.getTestAccounts())
20+
21+
const deployer = await graph.getDeployer()
22+
const indexers = indexerFixtures.map((i) => i.signer.address)
23+
const indexerETHBalances = indexerFixtures.map((i) => i.ethBalance)
24+
25+
// == Fund participants
26+
console.log('\n== Fund indexers')
27+
await fundAccountsETH(deployer, indexers, indexerETHBalances)
28+
29+
// == Time travel on local networks, ensure allocations can be closed
30+
if (['hardhat', 'localhost'].includes(hre.network.name)) {
31+
console.log('\n== Advancing to next epoch')
32+
await advanceToNextEpoch(graph.contracts.EpochManager)
33+
}
34+
35+
// == Close allocations
36+
console.log('\n== Close allocations')
37+
38+
for (const indexer of indexerFixtures) {
39+
for (const allocation of indexer.allocations.filter((a) => a.close)) {
40+
await closeAllocation(graph.contracts, indexer.signer, allocation.signer.address)
41+
}
42+
}
43+
}
44+
45+
// We recommend this pattern to be able to use async/await everywhere
46+
// and properly handle errors.
47+
main()
48+
.then(() => process.exit(0))
49+
.catch((error) => {
50+
console.error(error)
51+
process.exitCode = 1
52+
})
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { expect } from 'chai'
2+
import hre from 'hardhat'
3+
import { recreatePreviousSubgraphId } from './lib/subgraph'
4+
import { BigNumber } from 'ethers'
5+
import { CuratorFixture, getCuratorFixtures } from './fixtures/curators'
6+
import { SubgraphFixture, getSubgraphFixtures, getSubgraphOwner } from './fixtures/subgraphs'
7+
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
8+
9+
let curatorFixtures: CuratorFixture[]
10+
let subgraphFixtures: SubgraphFixture[]
11+
let subgraphOwnerFixture: SignerWithAddress
12+
13+
describe('Publish subgraphs', () => {
14+
const { contracts, getTestAccounts } = hre.graph()
15+
const { GNS, GraphToken, Curation } = contracts
16+
17+
before(async () => {
18+
const testAccounts = await getTestAccounts()
19+
curatorFixtures = getCuratorFixtures(testAccounts)
20+
subgraphFixtures = getSubgraphFixtures()
21+
subgraphOwnerFixture = getSubgraphOwner(testAccounts).signer
22+
})
23+
24+
describe('GRT balances', () => {
25+
it(`curator balances should match airdropped amount minus signalled`, async function () {
26+
for (const curator of curatorFixtures) {
27+
const address = curator.signer.address
28+
const balance = await GraphToken.balanceOf(address)
29+
expect(balance).eq(curator.grtBalance.sub(curator.signalled))
30+
}
31+
})
32+
})
33+
34+
describe('Subgraphs', () => {
35+
it(`should be published`, async function () {
36+
for (let i = 0; i < subgraphFixtures.length; i++) {
37+
const subgraphId = await recreatePreviousSubgraphId(
38+
contracts,
39+
subgraphOwnerFixture.address,
40+
subgraphFixtures.length - i,
41+
)
42+
const isPublished = await GNS.isPublished(subgraphId)
43+
expect(isPublished).eq(true)
44+
}
45+
})
46+
47+
it(`should have signal`, async function () {
48+
for (let i = 0; i < subgraphFixtures.length; i++) {
49+
const subgraph = subgraphFixtures[i]
50+
const subgraphId = await recreatePreviousSubgraphId(
51+
contracts,
52+
subgraphOwnerFixture.address,
53+
subgraphFixtures.length - i,
54+
)
55+
56+
let totalSignal: BigNumber = BigNumber.from(0)
57+
for (const curator of curatorFixtures) {
58+
const _subgraph = curator.subgraphs.find((s) => s.deploymentId === subgraph.deploymentId)
59+
if (_subgraph) {
60+
totalSignal = totalSignal.add(_subgraph.signal)
61+
}
62+
}
63+
64+
const tokens = await GNS.subgraphTokens(subgraphId)
65+
const MAX_PPM = 1000000
66+
const curationTax = await Curation.curationTaxPercentage()
67+
const tax = totalSignal.mul(curationTax).div(MAX_PPM)
68+
expect(tokens).eq(totalSignal.sub(tax))
69+
}
70+
})
71+
})
72+
})

e2e/scenarios/create-subgraphs.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// ### Scenario description ###
2+
// Common protocol actions > Set up subgraphs: publish and signal
3+
// This scenario will create a set of subgraphs and add signal to them. See fixtures for details.
4+
// Run with:
5+
// npx hardhat e2e:scenario create-subgraphs --network <network> --graph-config config/graph.<network>.yml
6+
7+
import hre from 'hardhat'
8+
import { publishNewSubgraph } from './lib/subgraph'
9+
import { fundAccountsETH, fundAccountsGRT } from './lib/accounts'
10+
import { signal } from './lib/curation'
11+
import { getSubgraphFixtures, getSubgraphOwner } from './fixtures/subgraphs'
12+
import { getCuratorFixtures } from './fixtures/curators'
13+
import { getGraphOptsFromArgv } from './lib/helpers'
14+
15+
async function main() {
16+
const graphOpts = getGraphOptsFromArgv()
17+
const graph = hre.graph(graphOpts)
18+
const testAccounts = await graph.getTestAccounts()
19+
20+
const subgraphFixtures = getSubgraphFixtures()
21+
const subgraphOwnerFixture = getSubgraphOwner(testAccounts)
22+
const curatorFixtures = getCuratorFixtures(testAccounts)
23+
24+
const deployer = await graph.getDeployer()
25+
const subgraphOwners = [subgraphOwnerFixture.signer.address]
26+
const subgraphOwnerETHBalance = [subgraphOwnerFixture.ethBalance]
27+
const curators = curatorFixtures.map((c) => c.signer.address)
28+
const curatorETHBalances = curatorFixtures.map((i) => i.ethBalance)
29+
const curatorGRTBalances = curatorFixtures.map((i) => i.grtBalance)
30+
31+
// == Fund participants
32+
console.log('\n== Fund subgraph owners and curators')
33+
await fundAccountsETH(
34+
deployer,
35+
[...subgraphOwners, ...curators],
36+
[...subgraphOwnerETHBalance, ...curatorETHBalances],
37+
)
38+
await fundAccountsGRT(deployer, curators, curatorGRTBalances, graph.contracts.GraphToken)
39+
40+
// == Publish subgraphs
41+
console.log('\n== Publishing subgraphs')
42+
43+
for (const subgraph of subgraphFixtures) {
44+
const id = await publishNewSubgraph(
45+
graph.contracts,
46+
subgraphOwnerFixture.signer,
47+
subgraph.deploymentId,
48+
)
49+
const subgraphData = subgraphFixtures.find((s) => s.deploymentId === subgraph.deploymentId)
50+
if (subgraphData) subgraphData.subgraphId = id
51+
}
52+
53+
// == Signal subgraphs
54+
console.log('\n== Signaling subgraphs')
55+
for (const curator of curatorFixtures) {
56+
for (const subgraph of curator.subgraphs) {
57+
const subgraphData = subgraphFixtures.find((s) => s.deploymentId === subgraph.deploymentId)
58+
if (subgraphData)
59+
await signal(graph.contracts, curator.signer, subgraphData.subgraphId, subgraph.signal)
60+
}
61+
}
62+
}
63+
64+
// We recommend this pattern to be able to use async/await everywhere
65+
// and properly handle errors.
66+
main()
67+
.then(() => process.exit(0))
68+
.catch((error) => {
69+
console.error(error)
70+
process.exitCode = 1
71+
})

0 commit comments

Comments
 (0)