Skip to content
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

More tests for the LSP contract #34

Draft
wants to merge 2 commits into
base: devel
Choose a base branch
from
Draft
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
28 changes: 28 additions & 0 deletions abis/OptomisticOracle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[
"constructor(uint256 _liveness, address _finderAddress, address _timerAddress)",
"event DisputePrice(address indexed requester, address indexed proposer, address indexed disputer, bytes32 identifier, uint256 timestamp, bytes ancillaryData, int256 proposedPrice)",
"event ProposePrice(address indexed requester, address indexed proposer, bytes32 identifier, uint256 timestamp, bytes ancillaryData, int256 proposedPrice, uint256 expirationTimestamp, address currency)",
"event RequestPrice(address indexed requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData, address currency, uint256 reward, uint256 finalFee)",
"event Settle(address indexed requester, address indexed proposer, address indexed disputer, bytes32 identifier, uint256 timestamp, bytes ancillaryData, int256 price, uint256 payout)",
"function ancillaryBytesLimit() view returns (uint256)",
"function defaultLiveness() view returns (uint256)",
"function disputePrice(address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData) returns (uint256 totalBond)",
"function disputePriceFor(address disputer, address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData) returns (uint256 totalBond)",
"function finder() view returns (address)",
"function getCurrentTime() view returns (uint256)",
"function getRequest(address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData) view returns (tuple(address proposer, address disputer, address currency, bool settled, bool refundOnDispute, int256 proposedPrice, int256 resolvedPrice, uint256 expirationTime, uint256 reward, uint256 finalFee, uint256 bond, uint256 customLiveness))",
"function getState(address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData) view returns (uint8)",
"function hasPrice(address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData) view returns (bool)",
"function proposePrice(address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData, int256 proposedPrice) returns (uint256 totalBond)",
"function proposePriceFor(address proposer, address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData, int256 proposedPrice) returns (uint256 totalBond)",
"function requestPrice(bytes32 identifier, uint256 timestamp, bytes ancillaryData, address currency, uint256 reward) returns (uint256 totalBond)",
"function requests(bytes32) view returns (address proposer, address disputer, address currency, bool settled, bool refundOnDispute, int256 proposedPrice, int256 resolvedPrice, uint256 expirationTime, uint256 reward, uint256 finalFee, uint256 bond, uint256 customLiveness)",
"function setBond(bytes32 identifier, uint256 timestamp, bytes ancillaryData, uint256 bond) returns (uint256 totalBond)",
"function setCurrentTime(uint256 time)",
"function setCustomLiveness(bytes32 identifier, uint256 timestamp, bytes ancillaryData, uint256 customLiveness)",
"function setRefundOnDispute(bytes32 identifier, uint256 timestamp, bytes ancillaryData)",
"function settle(address requester, bytes32 identifier, uint256 timestamp, bytes ancillaryData) returns (uint256 payout)",
"function settleAndGetPrice(bytes32 identifier, uint256 timestamp, bytes ancillaryData) returns (int256)",
"function stampAncillaryData(bytes ancillaryData, address requester) pure returns (bytes)",
"function timerAddress() view returns (address)"
]
25 changes: 14 additions & 11 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ task(
"convert",
"Convert all json abis to human readable format",
async (_, { ethers }) => {
const path = "~/abis/"
const path = "./abis/"
const files = await readdir(path)
for (const file of files) {
if (file === "index.ts") continue
const jsonBuffer = await readFile(path.concat(file))
const jsonAbi = JSON.parse(jsonBuffer.toString())
const iface = new ethers.utils.Interface(jsonAbi)
Expand Down Expand Up @@ -220,11 +221,12 @@ task("launch", "Launch all configured LSP contracts")

// Get Collateral Contract instance if not present already
if (!(contractConfiguration.collateralToken in contracts)) {
contracts[contractConfiguration.collateralToken] =
await ethers.getContractAt(
abis[contractConfiguration.collateralToken],
collateralTokenAddress
)
contracts[
contractConfiguration.collateralToken
] = await ethers.getContractAt(
abis[contractConfiguration.collateralToken],
collateralTokenAddress
)
}

// Create and Approve collateral for the proposer reward
Expand Down Expand Up @@ -289,11 +291,12 @@ task("launch", "Launch all configured LSP contracts")
// Configure Financial ProductLibrary
// Get Financial Product Library instance if not present already
if (!(contractConfiguration.financialProductLibrary in contracts)) {
contracts[contractConfiguration.financialProductLibrary] =
await ethers.getContractAt(
abis[contractConfiguration.financialProductLibrary],
financialProductLibraryAddress
)
contracts[
contractConfiguration.financialProductLibrary
] = await ethers.getContractAt(
abis[contractConfiguration.financialProductLibrary],
financialProductLibraryAddress
)
}

// Set Parameters
Expand Down
87 changes: 81 additions & 6 deletions test/contracts/LSP.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,33 @@
* @jest-environment node
*/

import { ethers, getNamedAccounts } from "hardhat"
import { config, ethers, getNamedAccounts } from "hardhat"
import { waffleJest } from "@ethereum-waffle/jest"
import { Address } from "hardhat-deploy/dist/types"
import { BigNumber, Contract } from "ethers"
import WETHAbi from "~/abis/WETH.json"
import LSPABI from "~/abis/LSP.json"
import LSPCreatorABI from "~/abis/LSPCreator.json"
import ERC20ABI from "~/abis/ERC20.json"
import OptimisticOracle from "~/abis/OptomisticOracle.json"
import LinearLongShortPairABI from "~/abis/LinearLongShortPairFinancialProductLibrary.json"

jest.setTimeout(40000)
expect.extend(waffleJest)

describe("LSP", function () {
const addresses: Record<string, Address> = {
const addresses = {
WETH: "0xd0a1e359811322d97991e03f863a0c30c2cf029c",
LSPCreator: "0x4C68829DBD07FEbB250B90f5624d4a5C30BBeC2c",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should use the addresses.json file here. I recently had the problem that the json file contained the outdated LSPCreator address leading to the issue that the redeeming worked in tests but not in the app, which was quite a confusing situation.

LinearLongShortPairFinancialProductLibrary:
"0x46b541E0fE2E817340A1A88740607329fF5ED279",
OptimisticOracle: "0xB1d3A89333BBC3F5e98A991d6d4C1910802986BC",
LSP: "",
longToken: "",
shortToken: "",
}
const contracts: Record<string, Contract> = {}
let namedAccounts: Record<string, Address>
let contracts: Record<keyof typeof addresses, Contract>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't run any tests because it complains that contracts is undefined.
I think you will have to initialize the variable here. (See old version)
image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately after changing that I still get a bunch of errors due to contract objects being undefined. Were you able to run the tests on your machine ? (If so what is the command you used?)

let namedAccounts: Record<keyof typeof config.namedAccounts, Address>

const gasprice = 50
const prepaidProposerReward = ethers.utils.parseUnits("0.01")
Expand All @@ -33,6 +38,7 @@ describe("LSP", function () {
const collateralPerPair = ethers.utils.parseUnits("1")
const tokensToKeep = tokensToCreate.sub(tokensToTransfer)
const tokensToRedeem = ethers.utils.parseUnits("1")
const tokensToSettle = ethers.utils.parseUnits("1")

beforeAll(async () => {
namedAccounts = await getNamedAccounts()
Expand Down Expand Up @@ -85,7 +91,7 @@ describe("LSP", function () {

const approvePromise = new Promise<void>((resolve) => {
contracts.WETH.once(
contracts.WETH.filters.Approval(null, addresses.EMP),
contracts.WETH.filters.Approval(null, addresses.LSP),
snake-poison marked this conversation as resolved.
Show resolved Hide resolved
(_1, _2, allowance) => {
expect(allowance).toEqBN(prepaidProposerReward)
resolve()
Expand Down Expand Up @@ -257,7 +263,7 @@ describe("LSP", function () {
)
expect(syntheticBalanceDeployer).toEqBN(tokensToKeep)
})
it("Sponsor can redeem remaining tokens", async function () {
it("Sponsor can redeem some tokens", async function () {
// Transaction parameters
const transactionOptions = {
gasPrice: gasprice * 1000000000, // gasprice arg * 1 GWEI
Expand Down Expand Up @@ -293,4 +299,73 @@ describe("LSP", function () {
const expectedCollateralBalance = oldCollateralBalance.add(tokensToRedeem)
expect(newCollateralBalance).toEqBN(expectedCollateralBalance)
})
it("Should change state to ExpiredPriceRequested after expire", async function () {
// Check that sponsor still has enough L / S Tokens
const syntheticBalances = await contracts.LSP.getPositionTokens(
namedAccounts.deployer
)
expect(syntheticBalances[0]).toBeGteBN(tokensToSettle)
expect(syntheticBalances[1]).toBeGteBN(tokensToSettle)

// Check contract state
const ContractState = {
Open: 0,
ExpiredPriceRequested: 1,
ExpiredPriceReceived: 2,
}

let contractState: number = await contracts.LSP.contractState()

expect(contractState).toEqual(ContractState.Open)

// fast forward 350 seconds
await ethers.provider.send("evm_increaseTime", [350])
snake-poison marked this conversation as resolved.
Show resolved Hide resolved
await ethers.provider.send("evm_mine", [])

// expire the contract
const expireTx = await contracts.LSP.expire()

await expireTx.wait()
contractState = await contracts.LSP.contractState()

expect(contractState).toEqual(ContractState.ExpiredPriceRequested)
})

it("Should change the contract state after calling expire", async function () {
// Check that sponsor still has enough L / S Tokens
const syntheticBalances = await contracts.LSP.getPositionTokens(
namedAccounts.deployer
)
expect(syntheticBalances[0]).toBeGteBN(tokensToSettle)
expect(syntheticBalances[1]).toBeGteBN(tokensToSettle)

// Check contract state
enum ContractState {
Open,
ExpiredPriceRequested,
ExpiredPriceReceived,
}

let contractState: number = await contracts.LSP.contractState()

expect(contractState).toEqual(ContractState.Open)

// fast forward 350 seconds
await ethers.provider.send("evm_increaseTime", [350])
await ethers.provider.send("evm_mine", [])

// expire the contract
const expireTx = await contracts.LSP.expire()

await expireTx.wait()
contractState = await contracts.LSP.contractState()

expect(contractState).toEqual(ContractState.ExpiredPriceRequested)
})
it("Should settle tokens after receiving expired price. ", async () => {
contracts.OptimisticOracle = await ethers.getContractAt(
snake-poison marked this conversation as resolved.
Show resolved Hide resolved
OptimisticOracle,
addresses.OptimisticOracle
)
})
})