Skip to content

Make block/epoch alignment in tests more predictable #555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const config: HardhatUserConfig = {
mnemonic: DEFAULT_TEST_MNEMONIC,
},
mining: {
auto: true,
auto: false,
interval: 30000,
},
hardfork: 'london',
Expand Down
2 changes: 1 addition & 1 deletion scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fi
mkdir -p reports

# Run using the standalone evm instance
npx hardhat test --network hardhat
npx hardhat test --network hardhat $@

### Cleanup

Expand Down
8 changes: 7 additions & 1 deletion test/lib/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { utils, Wallet, Signer } from 'ethers'

import * as deployment from './deployment'
import { evmSnapshot, evmRevert } from './testHelpers'
import { evmSnapshot, evmRevert, provider } from './testHelpers'

export class NetworkFixture {
lastSnapshotId: number
Expand All @@ -16,6 +16,12 @@ export class NetworkFixture {
slasher: Signer = Wallet.createRandom() as Signer,
arbitrator: Signer = Wallet.createRandom() as Signer,
): Promise<any> {
// Enable automining with each transaction, and disable
// the mining interval. Individual tests may modify this
// behavior as needed.
provider().send('evm_setIntervalMining', [0])
provider().send('evm_setAutomine', [true])

// Roles
const arbitratorAddress = await arbitrator.getAddress()
const slasherAddress = await slasher.getAddress()
Expand Down
9 changes: 4 additions & 5 deletions test/lib/testHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,13 @@ export const advanceBlocks = async (blocks: string | number | BigNumber): Promis
const steps = typeof blocks === 'number' || typeof blocks === 'string' ? toBN(blocks) : blocks
const currentBlock = await latestBlock()
const toBlock = currentBlock.add(steps)
await advanceBlockTo(toBlock)
return advanceBlockTo(toBlock)
}

export const advanceToNextEpoch = async (epochManager: EpochManager): Promise<void> => {
const currentBlock = await latestBlock()
const epochLength = await epochManager.epochLength()
const nextEpochBlock = currentBlock.add(epochLength)
await advanceBlockTo(nextEpochBlock)
const blocksSinceEpoch = await epochManager.currentEpochBlockSinceStart()
const epochLen = await epochManager.epochLength()
return advanceBlocks(epochLen.sub(blocksSinceEpoch))
}

export const evmSnapshot = async (): Promise<number> => provider().send('evm_snapshot', [])
Expand Down
47 changes: 38 additions & 9 deletions test/rewards/rewards.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,19 +573,29 @@ describe('Rewards', () => {
}

it('should distribute rewards on closed allocation and stake', async function () {

// Align with the epoch boundary
await advanceToNextEpoch(epochManager)
// Setup
await setupIndexerAllocation()

// Jump
await advanceBlocks(await epochManager.epochLength())
await advanceToNextEpoch(epochManager)

// Before state
const beforeTokenSupply = await grt.totalSupply()
const beforeIndexer1Stake = await staking.getIndexerStakedTokens(indexer1.address)
const beforeIndexer1Balance = await grt.balanceOf(indexer1.address)
const beforeStakingBalance = await grt.balanceOf(staking.address)

const expectedIndexingRewards = toGRT('1471954234')
// All the rewards in this subgraph go to this allocation.
// Rewards per token will be (totalSupply * issuanceRate^nBlocks - totalSupply) / allocatedTokens
// The first snapshot is after allocating, that is 2 blocks after the signal is minted:
// startRewardsPerToken = (10004000000 * 1.01227 ^ 2 - 10004000000) / 12500 = 122945.16
// The final snapshot is when we close the allocation, that happens 9 blocks later:
// endRewardsPerToken = (10004000000 * 1.01227 ^ 9 - 10004000000) / 12500 = 92861.24
// Then our expected rewards are (endRewardsPerToken - startRewardsPerToken) * 12500.
const expectedIndexingRewards = toGRT('913715958')

// Close allocation. At this point rewards should be collected for that indexer
const tx = await staking
Expand Down Expand Up @@ -623,19 +633,28 @@ describe('Rewards', () => {
const destinationAddress = randomHexBytes(20)
await staking.connect(indexer1.signer).setRewardsDestination(destinationAddress)

// Align with the epoch boundary
await advanceToNextEpoch(epochManager)
// Setup
await setupIndexerAllocation()

// Jump
await advanceBlocks(await epochManager.epochLength())
await advanceToNextEpoch(epochManager)

// Before state
const beforeTokenSupply = await grt.totalSupply()
const beforeIndexer1Stake = await staking.getIndexerStakedTokens(indexer1.address)
const beforeDestinationBalance = await grt.balanceOf(destinationAddress)
const beforeStakingBalance = await grt.balanceOf(staking.address)

const expectedIndexingRewards = toGRT('1471954234')
// All the rewards in this subgraph go to this allocation.
// Rewards per token will be (totalSupply * issuanceRate^nBlocks - totalSupply) / allocatedTokens
// The first snapshot is after allocating, that is 2 blocks after the signal is minted:
// startRewardsPerToken = (10004000000 * 1.01227 ^ 2 - 10004000000) / 12500 = 122945.16
// The final snapshot is when we close the allocation, that happens 9 blocks later:
// endRewardsPerToken = (10004000000 * 1.01227 ^ 9 - 10004000000) / 12500 = 92861.24
// Then our expected rewards are (endRewardsPerToken - startRewardsPerToken) * 12500.
const expectedIndexingRewards = toGRT('913715958')

// Close allocation. At this point rewards should be collected for that indexer
const tx = await staking
Expand Down Expand Up @@ -678,10 +697,13 @@ describe('Rewards', () => {
}
const tokensToDelegate = toGRT('2000')

// Align with the epoch boundary
await advanceToNextEpoch(epochManager)
// Setup the allocation and delegators
await setupIndexerAllocationWithDelegation(tokensToDelegate, delegationParams)

// Jump
await advanceBlocks(await epochManager.epochLength())
await advanceToNextEpoch(epochManager)

// Before state
const beforeTokenSupply = await grt.totalSupply()
Expand All @@ -698,8 +720,15 @@ describe('Rewards', () => {

// Check that rewards are put into indexer stake (only indexer cut)
// Check that rewards are put into delegators pool accordingly
// NOTE: calculated manually on a spreadsheet
const expectedIndexingRewards = toGRT('1454109066')

// All the rewards in this subgraph go to this allocation.
// Rewards per token will be (totalSupply * issuanceRate^nBlocks - totalSupply) / allocatedTokens
// The first snapshot is after allocating, that is 2 blocks after the signal is minted:
// startRewardsPerToken = (10004000000 * 1.01227 ^ 2 - 10004000000) / 14500 = 8466.995
// The final snapshot is when we close the allocation, that happens 4 blocks later:
// endRewardsPerToken = (10004000000 * 1.01227 ^ 4 - 10004000000) / 14500 = 34496.55
// Then our expected rewards are (endRewardsPerToken - startRewardsPerToken) * 14500.
const expectedIndexingRewards = toGRT('377428566.77')
// Calculate delegators cut
const indexerRewards = delegationParams.indexingRewardCut
.mul(expectedIndexingRewards)
Expand All @@ -725,7 +754,7 @@ describe('Rewards', () => {
await setupIndexerAllocation()

// Jump
await advanceBlocks(await epochManager.epochLength())
await advanceToNextEpoch(epochManager)

// Close allocation. At this point rewards should be collected for that indexer
const tx = staking.connect(indexer1.signer).closeAllocation(allocationID, randomHexBytes())
Expand Down Expand Up @@ -769,7 +798,7 @@ describe('Rewards', () => {
)

// Jump
await advanceBlocks(await epochManager.epochLength())
await advanceToNextEpoch(epochManager)

// Remove all signal from the subgraph
const curatorShares = await curation.getCuratorSignal(curator1.address, subgraphDeploymentID1)
Expand Down