feat: build and lint in ci

This commit is contained in:
Chance Hudson
2020-12-28 01:24:26 -06:00
committed by Wanseob Lim
parent 74a90718cb
commit 00892bade7
4 changed files with 260 additions and 75 deletions

30
.circleci/config.yml Normal file
View File

@@ -0,0 +1,30 @@
version: 2.1
workflows:
test_app:
jobs:
- build
jobs:
build:
machine:
image: ubuntu-2004:202010-01
steps:
- checkout
- run:
name: Install Yarn
command: curl -o- -L https://yarnpkg.com/install.sh | bash
- run:
name: Install
command: yarn
- run:
name: Build Prisma
command: yarn build:prisma
- run:
name: Lint
command: yarn lint .
- run:
name: Build Contract
command: yarn build:contract
- run:
name: Build TS
command: yarn build:ts:serial
no_output_timeout: 20m

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const { pathsToModuleNameMapper } = require('ts-jest/utils')
const { compilerOptions } = require('./tsconfig')
const base = require('./jest.config.base.js')

View File

@@ -18,6 +18,7 @@
"develop:instant": "yarn build:ts && docker-compose -f docker-compose.instant-block.yml up --build --force-recreate -V",
"build": "lerna run build:contract && lerna run build:prisma && yarn build:ts",
"build:ts": "lerna run --parallel build && yarn link-modules",
"build:ts:serial": "lerna run build && yarn link-modules",
"build:prisma": "lerna run build:prisma",
"build:contract": "lerna run --parallel build:contract",
"build:keys": "lerna run build-keys --scope=@zkopru/dataset",

View File

@@ -47,7 +47,9 @@ contract('BurnAuction tests', async accounts => {
})
chai.assert(false, 'Should fail to bid on earlier round')
} catch (err) {
chai.assert(err.reason === 'BurnAuction: Bid is too close to round start')
chai.assert(
err.reason === 'BurnAuction: Bid is too close to round start',
)
}
})
@@ -68,7 +70,9 @@ contract('BurnAuction tests', async accounts => {
})
chai.assert(false, 'Should fail to bid on later round')
} catch (err) {
chai.assert(err.reason === 'BurnAuction: Bid is too far from round start')
chai.assert(
err.reason === 'BurnAuction: Bid is too far from round start',
)
}
})
})
@@ -88,8 +92,14 @@ contract('BurnAuction tests', async accounts => {
it('should fail to bid on auction too close', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionEnd - 1)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionEnd - 1,
)
).toString()
try {
await burnAuction.bid(targetRound, {
from: accounts[0],
@@ -97,15 +107,21 @@ contract('BurnAuction tests', async accounts => {
chai.assert(false, 'Auction bid should fail')
} catch (err) {
chai.assert(
err.reason === 'BurnAuction: Bid is too close to round start'
err.reason === 'BurnAuction: Bid is too close to round start',
)
}
})
it('should fail to bid on auction too far', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionStart)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionStart,
)
).toString()
try {
await burnAuction.bid(targetRound, {
from: accounts[0],
@@ -113,7 +129,7 @@ contract('BurnAuction tests', async accounts => {
chai.assert(false, 'Auction bid should fail')
} catch (err) {
chai.assert(
err.reason === 'BurnAuction: Bid is too far from round start'
err.reason === 'BurnAuction: Bid is too far from round start',
)
}
})
@@ -125,9 +141,13 @@ contract('BurnAuction tests', async accounts => {
const targetRound = await burnAuction.earliestBiddableRound()
const bidAmount = new BN(web3.utils.toWei('1')) // 1 ether
try {
await burnAuction.methods['bid(uint256,uint256)'](targetRound, bidAmount, {
from: accounts[0],
})
await burnAuction.methods['bid(uint256,uint256)'](
targetRound,
bidAmount,
{
from: accounts[0],
},
)
chai.assert(false, 'Bid should fail')
} catch (err) {
chai.assert(err.reason === 'BurnAuction: Insufficient funds')
@@ -141,21 +161,24 @@ contract('BurnAuction tests', async accounts => {
const targetRound = await burnAuction.earliestBiddableRound()
const bidAmount = new BN(web3.utils.toWei('1')) // 1 ether
try {
await burnAuction.methods['bid(uint256,uint256)'](targetRound, bidAmount, {
from: accounts[0],
value: bidAmount,
})
await burnAuction.methods['bid(uint256,uint256)'](
targetRound,
bidAmount,
{
from: accounts[0],
value: bidAmount,
},
)
chai.assert(false, 'Bid should fail')
} catch (err) {
chai.assert(err.reason === undefined)
}
})
it('should fail to bid on past auction', async () => {
try {
await burnAuction.bid(0, {
from: accounts[0]
from: accounts[0],
})
chai.assert(false, 'Past auction bid should fail')
} catch (err) {
@@ -165,8 +188,14 @@ contract('BurnAuction tests', async accounts => {
it('should fail to bid if no url', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionEnd + 1)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionEnd + 1,
)
).toString()
const bidAmount = await burnAuction.minNextBid(targetRound)
try {
await burnAuction.bid(targetRound, {
@@ -219,9 +248,17 @@ contract('BurnAuction tests', async accounts => {
it('should fail to bid too little', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionStart/2)).toString()
const bidAmount = (await burnAuction.minNextBid(targetRound)).sub(new BN('1'))
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionStart / 2,
)
).toString()
const bidAmount = (await burnAuction.minNextBid(targetRound)).sub(
new BN('1'),
)
try {
await burnAuction.bid(targetRound, {
from: accounts[0],
@@ -235,9 +272,15 @@ contract('BurnAuction tests', async accounts => {
it('should refund bid when outbid', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionStart/2)).toString()
const bidAmount = (await burnAuction.minNextBid(targetRound))
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionStart / 2,
)
).toString()
const bidAmount = await burnAuction.minNextBid(targetRound)
// Do first bid
const originalBalance = await burnAuction.pendingBalances(accounts[0])
await burnAuction.bid(targetRound, {
@@ -266,7 +309,9 @@ contract('BurnAuction tests', async accounts => {
})
chai.assert(false, 'Should fail to bid on too near round')
} catch (err) {
chai.assert(err.reason === 'BurnAuction: Bid is too close to round start')
chai.assert(
err.reason === 'BurnAuction: Bid is too close to round start',
)
}
})
@@ -292,7 +337,7 @@ contract('BurnAuction tests', async accounts => {
const finalBalance = await burnAuction.pendingBalances(accounts[0])
chai.assert(
finalBalance.eq(startBalance.add(maxBid).sub(expectedTotalBid)),
'Final balance is incorrect'
'Final balance is incorrect',
)
})
@@ -317,14 +362,14 @@ contract('BurnAuction tests', async accounts => {
const highBid = await burnAuction.highestBidPerRound(x)
chai.assert(
highBid.owner === accounts[0],
`Expected account 0 to be round owner for round ${x}`
`Expected account 0 to be round owner for round ${x}`,
)
}
for (let x = +startRound + bidCount; x <= +endRound; x += 1) {
const highBid = await burnAuction.highestBidPerRound(x)
chai.assert(
highBid.owner === accounts[1],
`Expected account 1 to be round owner for round ${x}`
`Expected account 1 to be round owner for round ${x}`,
)
}
const finalBalance = await burnAuction.pendingBalances(accounts[0])
@@ -339,7 +384,10 @@ contract('BurnAuction tests', async accounts => {
from: accounts[1],
})
const networkUrl = await burnAuction.coordinatorUrls(accounts[1])
chai.assert(networkUrl === url, `Network url incorrect, expected ${url} got ${networkUrl}`)
chai.assert(
networkUrl === url,
`Network url incorrect, expected ${url} got ${networkUrl}`,
)
})
it('should clear url', async () => {
@@ -348,29 +396,48 @@ contract('BurnAuction tests', async accounts => {
from: accounts[1],
})
const networkUrl = await burnAuction.coordinatorUrls(accounts[1])
chai.assert(networkUrl === url, `First network url incorrect, expected ${url} got ${networkUrl}`)
chai.assert(
networkUrl === url,
`First network url incorrect, expected ${url} got ${networkUrl}`,
)
await burnAuction.clearUrl({
from: accounts[1],
})
const newNetworkUrl = await burnAuction.coordinatorUrls(accounts[1])
chai.assert(newNetworkUrl === '', `Second network url incorrect, expected nothing got ${newNetworkUrl}`)
chai.assert(
newNetworkUrl === '',
`Second network url incorrect, expected nothing got ${newNetworkUrl}`,
)
})
})
describe('refund test', () => {
it('should refund empty balance', async () => {
const contractBalance = new BN(await web3.eth.getBalance(burnAuction.address, 'latest'))
const contractBalance = new BN(
await web3.eth.getBalance(burnAuction.address, 'latest'),
)
await burnAuction.refund({
from: accounts[9],
})
const newContractBalance = new BN(await web3.eth.getBalance(burnAuction.address, 'latest'))
chai.assert(contractBalance.eq(newContractBalance), 'Contract balance should not change')
const newContractBalance = new BN(
await web3.eth.getBalance(burnAuction.address, 'latest'),
)
chai.assert(
contractBalance.eq(newContractBalance),
'Contract balance should not change',
)
})
it('should refund balance once', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionStart/2)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionStart / 2,
)
).toString()
await burnAuction.setUrl('localhost', {
from: accounts[3],
})
@@ -384,32 +451,46 @@ contract('BurnAuction tests', async accounts => {
value: await burnAuction.minNextBid(targetRound),
})
const pendingBalance = await burnAuction.pendingBalances(accounts[3])
const addressBalance = new BN(await web3.eth.getBalance(accounts[3], 'latest'))
const addressBalance = new BN(
await web3.eth.getBalance(accounts[3], 'latest'),
)
// Use alt account to avoid gas cost calculation
await burnAuction.methods['refund(address)'](accounts[3], {
from: accounts[9],
})
const finalBalance = new BN(await web3.eth.getBalance(accounts[3], 'latest'))
const finalBalance = new BN(
await web3.eth.getBalance(accounts[3], 'latest'),
)
chai.assert(addressBalance.add(pendingBalance).eq(finalBalance))
const newPendingBalance = await burnAuction.pendingBalances(accounts[3])
chai.assert(newPendingBalance.eq(new BN('0')))
await burnAuction.methods['refund(address)'](accounts[3], {
from: accounts[9],
})
const _finalBalance = new BN(await web3.eth.getBalance(accounts[3], 'latest'))
chai.assert(_finalBalance.eq(finalBalance))
const finalBalance2 = new BN(
await web3.eth.getBalance(accounts[3], 'latest'),
)
chai.assert(finalBalance2.eq(finalBalance))
})
})
describe('open round tests', () => {
it('should not open round', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionEnd)).toString()
const targetRoundStart = +(await burnAuction.calcRoundStart(targetRound)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionEnd,
)
).toString()
const targetRoundStart = +(
await burnAuction.calcRoundStart(targetRound)
).toString()
const bidAmount = await burnAuction.minNextBid(targetRound)
await burnAuction.setUrl('localhost', {
from: accounts[5]
from: accounts[5],
})
await burnAuction.bid(targetRound, {
from: accounts[5],
@@ -419,25 +500,44 @@ contract('BurnAuction tests', async accounts => {
while ((await web3.eth.getBlock('latest')).number < targetRoundStart) {
await timeMachine.advanceBlock()
}
chai.assert(+(await burnAuction.currentRound()).toString() === targetRound)
chai.assert(
+(await burnAuction.currentRound()).toString() === targetRound,
)
// now we're in the round controlled by accounts[5]
chai.assert(!(await burnAuction.isRoundOpen()), 'Round is already open')
await burnAuction.openRoundIfNeeded()
chai.assert(!(await burnAuction.isRoundOpen()), 'Round should not be opened')
chai.assert(
!(await burnAuction.isRoundOpen()),
'Round should not be opened',
)
await zkopru.propose(accounts[5])
// advance the blockchain further
while ((await web3.eth.getBlock('latest')).number < targetRoundStart + roundLength / 2) {
while (
(await web3.eth.getBlock('latest')).number <
targetRoundStart + roundLength / 2
) {
await timeMachine.advanceBlock()
}
await burnAuction.openRoundIfNeeded()
chai.assert(!(await burnAuction.isRoundOpen()), 'Round should not be opened after half')
chai.assert(
!(await burnAuction.isRoundOpen()),
'Round should not be opened after half',
)
})
it('should open round if no proposed block in first half', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionEnd)).toString()
const targetRoundStart = +(await burnAuction.calcRoundStart(targetRound)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionEnd,
)
).toString()
const targetRoundStart = +(
await burnAuction.calcRoundStart(targetRound)
).toString()
const bidAmount = await burnAuction.minNextBid(targetRound)
await burnAuction.bid(targetRound, {
from: accounts[5],
@@ -447,17 +547,28 @@ contract('BurnAuction tests', async accounts => {
while ((await web3.eth.getBlock('latest')).number < targetRoundStart) {
await timeMachine.advanceBlock()
}
chai.assert(+(await burnAuction.currentRound()).toString() === targetRound)
chai.assert(
+(await burnAuction.currentRound()).toString() === targetRound,
)
// now we're in the round controlled by accounts[5]
chai.assert(!(await burnAuction.isRoundOpen()), 'Round is already open')
await burnAuction.openRoundIfNeeded()
chai.assert(!(await burnAuction.isRoundOpen()), 'Round should not be opened')
chai.assert(
!(await burnAuction.isRoundOpen()),
'Round should not be opened',
)
// advance the blockchain past halfway point
while ((await web3.eth.getBlock('latest')).number < targetRoundStart + roundLength / 2) {
while (
(await web3.eth.getBlock('latest')).number <
targetRoundStart + roundLength / 2
) {
await timeMachine.advanceBlock()
}
await burnAuction.openRoundIfNeeded()
chai.assert(await burnAuction.isRoundOpen(), 'Round should be opened after half')
chai.assert(
await burnAuction.isRoundOpen(),
'Round should be opened after half',
)
})
})
@@ -511,7 +622,7 @@ contract('BurnAuction tests', async accounts => {
const expectedBalance = balance.add(startBalance)
chai.assert(
newBalance.eq(expectedBalance),
`Incorrect balance, expected ${expectedBalance.toString()} got ${newBalance.toString()}`
`Incorrect balance, expected ${expectedBalance.toString()} got ${newBalance.toString()}`,
)
// Jump further in the future
const targetBlock2 = await burnAuction.calcRoundStart(finalRound + 5)
@@ -532,7 +643,7 @@ contract('BurnAuction tests', async accounts => {
const finalNewBalance = await burnAuction.balance()
chai.assert(
finalNewBalance.eq(finalExpectedBalance),
`Incorrect second balance`
`Incorrect second balance`,
)
})
@@ -607,12 +718,12 @@ contract('BurnAuction tests', async accounts => {
const lastBalanceIndex = await burnAuction.lastBalanceIndex()
chai.assert(
+lastBalanceIndex === finalRound,
'Not settled to current round'
'Not settled to current round',
)
const finalBalance = await burnAuction.balance()
chai.assert(
finalBalance.eq(balance.add(expectedProfit)),
'Unexpected balance'
'Unexpected balance',
)
})
@@ -627,18 +738,32 @@ contract('BurnAuction tests', async accounts => {
from: accounts[8],
})
const balance = new BN(await web3.eth.getBalance(receiver, 'latest'))
chai.assert(startBalance.add(contractBalance).eq(balance), 'Funds were not received')
chai.assert(
startBalance.add(contractBalance).eq(balance),
'Funds were not received',
)
const newContractBalance = await burnAuction.balance()
chai.assert(newContractBalance.eq(new BN('0')), 'Not all funds were moved')
chai.assert(
newContractBalance.eq(new BN('0')),
'Not all funds were moved',
)
})
})
describe('round tests', () => {
it('should propose if winning bid', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionEnd)).toString()
const targetRoundStart = +(await burnAuction.calcRoundStart(targetRound)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionEnd,
)
).toString()
const targetRoundStart = +(
await burnAuction.calcRoundStart(targetRound)
).toString()
const bidAmount = await burnAuction.minNextBid(targetRound)
await burnAuction.bid(targetRound, {
from: accounts[0],
@@ -647,7 +772,9 @@ contract('BurnAuction tests', async accounts => {
while ((await web3.eth.getBlock('latest')).number < targetRoundStart) {
await timeMachine.advanceBlock()
}
chai.assert(+(await burnAuction.currentRound()).toString() === targetRound)
chai.assert(
+(await burnAuction.currentRound()).toString() === targetRound,
)
chai.assert(await burnAuction.isProposable(accounts[0]))
chai.assert(!(await burnAuction.isProposable(accounts[1])))
})
@@ -658,16 +785,21 @@ contract('BurnAuction tests', async accounts => {
// find a round that has no bids
for (let x = currentRound + 1; true; x += 1) {
const highBid = await burnAuction.highestBidPerRound(x)
// eslint-disable-next-line jest/no-if
if (highBid.amount.eq(new BN('0'))) {
targetRound = x
break
}
}
const targetRoundStart = +(await burnAuction.calcRoundStart(targetRound)).toString()
const targetRoundStart = +(
await burnAuction.calcRoundStart(targetRound)
).toString()
while ((await web3.eth.getBlock('latest')).number < targetRoundStart) {
await timeMachine.advanceBlock()
}
chai.assert(+(await burnAuction.currentRound()).toString() === targetRound)
chai.assert(
+(await burnAuction.currentRound()).toString() === targetRound,
)
chai.assert(await burnAuction.isProposable(accounts[0]))
chai.assert(await burnAuction.isProposable(accounts[1]))
chai.assert(await burnAuction.isProposable(accounts[2]))
@@ -677,22 +809,37 @@ contract('BurnAuction tests', async accounts => {
describe('lock tests', () => {
it('should fail to lock', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionStart - 1)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionStart - 1,
)
).toString()
try {
await zkopru.lock(targetRound, {
from: accounts[0],
})
chai.assert(false, 'Should fail to lock')
} catch (err) {
chai.assert(err.reason === 'BurnAuction: Round index is not far enough in the future')
chai.assert(
err.reason ===
'BurnAuction: Round index is not far enough in the future',
)
}
})
it('should lock', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionStart + 1)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionStart + 1,
)
).toString()
await zkopru.lock(targetRound, {
from: accounts[0],
})
@@ -713,8 +860,14 @@ contract('BurnAuction tests', async accounts => {
it('should fail to double lock', async () => {
const currentRound = +(await burnAuction.currentRound()).toString()
const roundStartBlock = +(await burnAuction.calcRoundStart(currentRound)).toString()
const targetRound = +(await burnAuction.roundForBlock(roundStartBlock + roundLength + auctionStart + 1)).toString()
const roundStartBlock = +(
await burnAuction.calcRoundStart(currentRound)
).toString()
const targetRound = +(
await burnAuction.roundForBlock(
roundStartBlock + roundLength + auctionStart + 1,
)
).toString()
try {
await zkopru.lock(targetRound, {
from: accounts[0],