forked from keep3r-network/ff
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: added test scaffolding (keep3r-network#2)
* chore: added hardhat boilerplate * chore: run linter * fix: rm legacy code * feat: added vyper compiler * feat: added github workflows * fix: linter error * feat: adding basic test structure * fix: typings bug * feat: added tests scaffolding * fix: revert linter * fix: run prettier
- Loading branch information
1 parent
5e79b10
commit 1f9cd61
Showing
17 changed files
with
440 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { getMainnetSdk } from '@dethcrypto/eth-sdk-client'; | ||
import { Keep3rV1 } from '@eth-sdk-types'; | ||
import { FixedForex, FixedForex__factory } from '@typechained'; | ||
import { ethers } from 'hardhat'; | ||
import { evm } from '@utils'; | ||
import { expect } from 'chai'; | ||
import { getNodeUrl } from 'utils/env'; | ||
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; | ||
|
||
describe('FixedForex @skip-on-coverage', () => { | ||
let deployer: SignerWithAddress; | ||
let keep3rV1: Keep3rV1; | ||
let snapshotId: string; | ||
let fixedForex: FixedForex; | ||
|
||
before(async () => { | ||
[deployer] = await ethers.getSigners(); | ||
|
||
await evm.reset({ | ||
jsonRpcUrl: getNodeUrl('ethereum'), | ||
blockNumber: 14750000, | ||
}); | ||
|
||
const sdk = getMainnetSdk(deployer); | ||
keep3rV1 = sdk.keep3rV1; | ||
|
||
const fixedForexFactory = (await ethers.getContractFactory('FixedForex')) as FixedForex__factory; | ||
fixedForex = await fixedForexFactory.connect(deployer).deploy(keep3rV1.address); | ||
|
||
snapshotId = await evm.snapshot.take(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
await evm.snapshot.revert(snapshotId); | ||
}); | ||
|
||
describe('fixed-forex', () => { | ||
it('should be deployed', async () => { | ||
expect(await fixedForex.deployed()); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import chai, { expect } from 'chai'; | ||
import { MockContract, MockContractFactory, smock } from '@defi-wonderland/smock'; | ||
import { GaugeProxy, GaugeProxy__factory } from '@typechained'; | ||
import { evm } from '@utils'; | ||
|
||
chai.use(smock.matchers); | ||
|
||
describe('GaugeProxy', () => { | ||
let gauge: MockContract<GaugeProxy>; | ||
let gaugeFactory: MockContractFactory<GaugeProxy__factory>; | ||
let snapshotId: string; | ||
|
||
before(async () => { | ||
gaugeFactory = await smock.mock<GaugeProxy__factory>('GaugeProxy'); | ||
gauge = await gaugeFactory.deploy(); | ||
snapshotId = await evm.snapshot.take(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
await evm.snapshot.revert(snapshotId); | ||
}); | ||
|
||
it('should be deployed', async () => { | ||
expect(await gauge.deployed()); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Suite, SuiteFunction } from 'mocha'; | ||
|
||
export const then = it; | ||
export const given = beforeEach; | ||
export const when: SuiteFunction = <SuiteFunction>function (title: string, fn: (this: Suite) => void) { | ||
context('when ' + title, fn); | ||
}; | ||
when.only = (title: string, fn?: (this: Suite) => void) => context.only('when ' + title, fn!); | ||
when.skip = (title: string, fn: (this: Suite) => void) => context.skip('when ' + title, fn); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { smock } from '@defi-wonderland/smock'; | ||
import { Provider } from '@ethersproject/providers'; | ||
import chai, { expect } from 'chai'; | ||
import { Signer } from 'ethers'; | ||
import { contracts, wallet } from '.'; | ||
import { toUnit } from './bn'; | ||
|
||
chai.use(smock.matchers); | ||
|
||
export type Impersonator = Signer | Provider | string; | ||
|
||
export const onlyMaker = createOnlyCallableCheck(['maker'], 'OnlyMaker()'); | ||
export const onlyKeeper = createOnlyCallableCheck(['keeper'], 'OnlyKeeper()'); | ||
export const onlyGovernor = createOnlyCallableCheck(['governance'], 'OnlyGovernor()'); | ||
export const onlyPendingGovernor = createOnlyCallableCheck(['pending governance'], 'OnlyPendingGovernor()'); | ||
|
||
export function createOnlyCallableCheck(allowedLabels: string[], error: string) { | ||
return ( | ||
delayedContract: () => any, | ||
fnName: string, | ||
allowedWallet: Impersonator | Impersonator[] | (() => Impersonator | Impersonator[]), | ||
args: unknown[] | (() => unknown[]) | ||
) => { | ||
allowedLabels.forEach((allowedLabel, index) => { | ||
it(`should be callable by ${allowedLabel}`, async () => { | ||
let impersonator = allowedWallet; | ||
if (typeof allowedWallet === 'function') impersonator = allowedWallet(); | ||
if (Array.isArray(impersonator)) impersonator = impersonator[index]; | ||
|
||
return expect(callFunction(impersonator as Impersonator)).not.to.be.revertedWith(error); | ||
}); | ||
}); | ||
|
||
it('should not be callable by any address', async () => { | ||
const any = await wallet.generateRandom(); | ||
await wallet.setBalance({ account: any.address, balance: toUnit(1) }); | ||
return expect(callFunction(any)).to.be.revertedWith(error); | ||
}); | ||
|
||
function callFunction(impersonator: Impersonator) { | ||
const argsArray: unknown[] = typeof args === 'function' ? args() : args; | ||
const fn = delayedContract().connect(impersonator)[fnName] as (...args: unknown[]) => unknown; | ||
return fn(...argsArray, { | ||
gasLimit: 1e6, | ||
gasPrice: 500e9, | ||
}); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { BigNumber, utils } from 'ethers'; | ||
import { expect } from 'chai'; | ||
|
||
export const expectToEqualWithThreshold = ({ | ||
value, | ||
to, | ||
threshold, | ||
}: { | ||
value: BigNumber | number | string; | ||
to: BigNumber | number | string; | ||
threshold: BigNumber | number | string; | ||
}): void => { | ||
value = toBN(value); | ||
to = toBN(to); | ||
threshold = toBN(threshold); | ||
expect( | ||
to.sub(threshold).lte(value) && to.add(threshold).gte(value), | ||
`Expected ${value.toString()} to be between ${to.sub(threshold).toString()} and ${to.add(threshold).toString()}` | ||
).to.be.true; | ||
}; | ||
|
||
export const toBN = (value: string | number | BigNumber): BigNumber => { | ||
return BigNumber.isBigNumber(value) ? value : BigNumber.from(value); | ||
}; | ||
|
||
export const toUnit = (value: number): BigNumber => { | ||
return utils.parseUnits(value.toString()); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; | ||
export const ETH_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Contract, ContractFactory } from '@ethersproject/contracts'; | ||
import { TransactionResponse } from '@ethersproject/abstract-provider'; | ||
import { ContractInterface, Signer } from 'ethers'; | ||
import { getStatic } from 'ethers/lib/utils'; | ||
|
||
export const deploy = async (contract: ContractFactory, args: any[]): Promise<{ tx: TransactionResponse; contract: Contract }> => { | ||
const deploymentTransactionRequest = await contract.getDeployTransaction(...args); | ||
const deploymentTx = await contract.signer.sendTransaction(deploymentTransactionRequest); | ||
const contractAddress = getStatic<(deploymentTx: TransactionResponse) => string>(contract.constructor, 'getContractAddress')(deploymentTx); | ||
const deployedContract = getStatic<(contractAddress: string, contractInterface: ContractInterface, signer?: Signer) => Contract>( | ||
contract.constructor, | ||
'getContract' | ||
)(contractAddress, contract.interface, contract.signer); | ||
return { | ||
tx: deploymentTx, | ||
contract: deployedContract, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { BigNumber, Contract } from 'ethers'; | ||
import { ethers } from 'hardhat'; | ||
|
||
export const deploy = async ({ | ||
name, | ||
symbol, | ||
decimals, | ||
initialAccount, | ||
initialAmount, | ||
}: { | ||
name: string; | ||
symbol: string; | ||
decimals?: BigNumber | number; | ||
initialAccount: string; | ||
initialAmount: BigNumber; | ||
}): Promise<Contract> => { | ||
const erc20MockContract = await ethers.getContractFactory('contracts/mocks/ERC20Mock.sol:ERC20Mock'); | ||
const deployedContract = await erc20MockContract.deploy(name, symbol, decimals || 18, initialAccount, initialAmount); | ||
return deployedContract; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { TransactionResponse, TransactionReceipt } from '@ethersproject/abstract-provider'; | ||
import { expect } from 'chai'; | ||
|
||
export async function expectNoEventWithName(response: TransactionResponse, eventName: string) { | ||
const receipt = await response.wait(); | ||
for (const event of getEvents(receipt)) { | ||
expect(event.event).not.to.equal(eventName); | ||
} | ||
} | ||
|
||
export async function readArgFromEvent<T>(response: TransactionResponse, eventName: string, paramName: string): Promise<T | undefined> { | ||
const receipt = await response.wait(); | ||
for (const event of getEvents(receipt)) { | ||
if (event.event === eventName) { | ||
return event.args[paramName]; | ||
} | ||
} | ||
} | ||
|
||
export async function readArgFromEventOrFail<T>(response: TransactionResponse, eventName: string, paramName: string): Promise<T> { | ||
const result = await readArgFromEvent<T>(response, eventName, paramName); | ||
if (result) { | ||
return result; | ||
} | ||
throw new Error(`Failed to find event with name ${eventName}`); | ||
} | ||
|
||
function getEvents(receipt: TransactionReceipt): Event[] { | ||
// @ts-ignore | ||
return receipt.events; | ||
} | ||
|
||
type Event = { | ||
event: string; // Event name | ||
args: any; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { BigNumber, BigNumberish } from 'ethers'; | ||
import { network } from 'hardhat'; | ||
|
||
export const advanceTimeAndBlock = async (time: number): Promise<void> => { | ||
await advanceTime(time); | ||
await advanceBlocks(1); | ||
}; | ||
|
||
export const advanceToTimeAndBlock = async (time: number): Promise<void> => { | ||
await advanceToTime(time); | ||
await advanceBlocks(1); | ||
}; | ||
|
||
export const advanceTime = async (time: number): Promise<void> => { | ||
await network.provider.request({ | ||
method: 'evm_increaseTime', | ||
params: [time], | ||
}); | ||
}; | ||
|
||
export const advanceToTime = async (time: number): Promise<void> => { | ||
await network.provider.request({ | ||
method: 'evm_setNextBlockTimestamp', | ||
params: [time], | ||
}); | ||
}; | ||
|
||
export const advanceBlocks = async (blocks: BigNumberish) => { | ||
blocks = !BigNumber.isBigNumber(blocks) ? BigNumber.from(`${blocks}`) : blocks; | ||
await network.provider.request({ | ||
method: 'hardhat_mine', | ||
params: [blocks.toHexString().replace('0x0', '0x')], | ||
}); | ||
}; | ||
|
||
export const reset = async (forking?: { [key: string]: any }) => { | ||
const params = forking ? [{ forking }] : []; | ||
await network.provider.request({ | ||
method: 'hardhat_reset', | ||
params, | ||
}); | ||
}; | ||
|
||
class SnapshotManager { | ||
snapshots: { [id: string]: string } = {}; | ||
|
||
async take(): Promise<string> { | ||
const id = await this.takeSnapshot(); | ||
this.snapshots[id] = id; | ||
return id; | ||
} | ||
|
||
async revert(id: string): Promise<void> { | ||
await this.revertSnapshot(this.snapshots[id]); | ||
this.snapshots[id] = await this.takeSnapshot(); | ||
} | ||
|
||
private async takeSnapshot(): Promise<string> { | ||
return (await network.provider.request({ | ||
method: 'evm_snapshot', | ||
params: [], | ||
})) as string; | ||
} | ||
|
||
private async revertSnapshot(id: string) { | ||
await network.provider.request({ | ||
method: 'evm_revert', | ||
params: [id], | ||
}); | ||
} | ||
} | ||
|
||
export const snapshot = new SnapshotManager(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import * as behaviours from './behaviours'; | ||
import * as contracts from './contracts'; | ||
import * as erc20 from './erc20'; | ||
import * as evm from './evm'; | ||
import * as bn from './bn'; | ||
import * as wallet from './wallet'; | ||
|
||
export { contracts, behaviours, bn, erc20, evm, wallet }; |
Oops, something went wrong.