96cad7de9c
* tests: reorganize testing packages * gitignore and minor changes
177 lines
8.5 KiB
JavaScript
177 lines
8.5 KiB
JavaScript
const { assertRevert } = require('@aragon/contract-helpers-test/assertThrow')
|
|
const { bn, assertBn, MAX_UINT64 } = require('@aragon/contract-helpers-test/numbers')
|
|
|
|
const { deploy } = require('./helpers/deploy')(artifacts)
|
|
const { approveAndStake } = require('./helpers/helpers')(artifacts)
|
|
const { DEFAULT_STAKE_AMOUNT, EMPTY_DATA } = require('./helpers/constants')
|
|
const { STAKING_ERRORS } = require('./helpers/errors')
|
|
|
|
const StakingMock = artifacts.require('StakingMock')
|
|
const StandardTokenMock = artifacts.require('StandardTokenMock');
|
|
const BadTokenMock = artifacts.require('BadTokenMock')
|
|
|
|
const getTokenBalance = async (token, account) => await token.balanceOf(account)
|
|
|
|
contract('Staking app', ([owner, other]) => {
|
|
let staking, token, stakingAddress, tokenAddress
|
|
|
|
beforeEach(async () => {
|
|
const initialAmount = DEFAULT_STAKE_AMOUNT.mul(bn(1000))
|
|
const tokenContract = await StandardTokenMock.new(owner, initialAmount)
|
|
token = tokenContract
|
|
tokenAddress = tokenContract.address
|
|
await token.mint(other, DEFAULT_STAKE_AMOUNT)
|
|
const stakingContract = await StakingMock.new(tokenAddress)
|
|
staking = stakingContract
|
|
stakingAddress = stakingContract.address
|
|
})
|
|
|
|
it('has correct initial state', async () => {
|
|
assert.equal(await staking.token(), tokenAddress, "Token is wrong")
|
|
assert.equal((await staking.totalStaked()).valueOf(), 0, "Initial total staked amount should be zero")
|
|
assert.equal(await staking.supportsHistory(), true, "history support should match")
|
|
})
|
|
|
|
it('fails deploying if token is not a contract', async() => {
|
|
await assertRevert(StakingMock.new(owner)/*, STAKING_ERRORS.ERROR_TOKEN_NOT_CONTRACT*/)
|
|
})
|
|
|
|
it('stakes', async () => {
|
|
const initialOwnerBalance = await getTokenBalance(token, owner)
|
|
const initialStakingBalance = await getTokenBalance(token, stakingAddress)
|
|
|
|
await approveAndStake({ staking, from: owner })
|
|
|
|
const finalOwnerBalance = await getTokenBalance(token, owner)
|
|
const finalStakingBalance = await getTokenBalance(token, stakingAddress)
|
|
assertBn(finalOwnerBalance, initialOwnerBalance.sub(bn(DEFAULT_STAKE_AMOUNT)), "owner balance should match")
|
|
assertBn(finalStakingBalance, initialStakingBalance.add(bn(DEFAULT_STAKE_AMOUNT)), "Staking app balance should match")
|
|
assertBn(await staking.totalStakedFor(owner), bn(DEFAULT_STAKE_AMOUNT), "staked value should match")
|
|
// total stake
|
|
assertBn(await staking.totalStaked(), bn(DEFAULT_STAKE_AMOUNT), "Total stake should match")
|
|
})
|
|
|
|
it('fails staking 0 amount', async () => {
|
|
await token.approve(stakingAddress, 1)
|
|
await assertRevert(staking.stake(0, EMPTY_DATA)/*, STAKING_ERRORS.ERROR_AMOUNT_ZERO*/)
|
|
})
|
|
|
|
it('fails staking more than balance', async () => {
|
|
const balance = await getTokenBalance(token, owner)
|
|
const amount = balance.add(bn(1))
|
|
await token.approve(stakingAddress, amount)
|
|
await assertRevert(staking.stake(amount, EMPTY_DATA)/*, STAKING_ERRORS.ERROR_TOKEN_DEPOSIT*/)
|
|
})
|
|
|
|
it('stakes for', async () => {
|
|
const initialOwnerBalance = await getTokenBalance(token, owner)
|
|
const initialOtherBalance = await getTokenBalance(token, other)
|
|
const initialStakingBalance = await getTokenBalance(token, stakingAddress)
|
|
|
|
// allow Staking app to move owner tokens
|
|
await token.approve(stakingAddress, DEFAULT_STAKE_AMOUNT)
|
|
// stake tokens
|
|
await staking.stakeFor(other, DEFAULT_STAKE_AMOUNT, EMPTY_DATA)
|
|
|
|
const finalOwnerBalance = await getTokenBalance(token, owner)
|
|
const finalOtherBalance = await getTokenBalance(token, other)
|
|
const finalStakingBalance = await getTokenBalance(token, stakingAddress)
|
|
assertBn(finalOwnerBalance, initialOwnerBalance.sub(bn(DEFAULT_STAKE_AMOUNT)), "owner balance should match")
|
|
assertBn(finalOtherBalance, initialOtherBalance, "other balance should match")
|
|
assertBn(finalStakingBalance, initialStakingBalance.add(bn(DEFAULT_STAKE_AMOUNT)), "Staking app balance should match")
|
|
assertBn(await staking.totalStakedFor(owner), bn(0), "staked value for owner should match")
|
|
assertBn(await staking.totalStakedFor(other), bn(DEFAULT_STAKE_AMOUNT), "staked value for other should match")
|
|
})
|
|
|
|
it('unstakes', async () => {
|
|
const initialOwnerBalance = await getTokenBalance(token, owner)
|
|
const initialStakingBalance = await getTokenBalance(token, stakingAddress)
|
|
|
|
await approveAndStake({ staking, from: owner })
|
|
|
|
// unstake half of them
|
|
await staking.unstake(DEFAULT_STAKE_AMOUNT.div(bn(2)), EMPTY_DATA)
|
|
|
|
const finalOwnerBalance = await getTokenBalance(token, owner)
|
|
const finalStakingBalance = await getTokenBalance(token, stakingAddress)
|
|
assertBn(finalOwnerBalance, initialOwnerBalance.sub(bn(DEFAULT_STAKE_AMOUNT.div(bn(2)))), "owner balance should match")
|
|
assertBn(finalStakingBalance, initialStakingBalance.add(bn(DEFAULT_STAKE_AMOUNT.div(bn(2)))), "Staking app balance should match")
|
|
assertBn(await staking.totalStakedFor(owner), bn(DEFAULT_STAKE_AMOUNT.div(bn(2))), "staked value should match")
|
|
})
|
|
|
|
it('fails unstaking 0 amount', async () => {
|
|
await approveAndStake({ staking, from: owner })
|
|
await assertRevert(staking.unstake(0, EMPTY_DATA)/*, STAKING_ERRORS.ERROR_AMOUNT_ZERO*/)
|
|
})
|
|
|
|
it('fails unstaking more than staked', async () => {
|
|
await approveAndStake({ staking, from: owner })
|
|
await assertRevert(staking.unstake(DEFAULT_STAKE_AMOUNT.add(bn(1)), EMPTY_DATA)/*, STAKING_ERRORS.ERROR_NOT_ENOUGH_BALANCE*/)
|
|
})
|
|
|
|
context('History', async () => {
|
|
it('supports history', async () => {
|
|
assert.equal(await staking.supportsHistory(), true, "It should support History")
|
|
})
|
|
|
|
it('has correct "last staked for"', async () => {
|
|
const blockNumber = await staking.getBlockNumberPublic()
|
|
const lastStaked = blockNumber.add(bn(5))
|
|
await staking.setBlockNumber(lastStaked)
|
|
await approveAndStake({ staking, from: owner })
|
|
assertBn(await staking.lastStakedFor(owner), lastStaked, "Last staked for should match")
|
|
})
|
|
|
|
it('has correct "total staked for at"', async () => {
|
|
const beforeBlockNumber = await staking.getBlockNumberPublic()
|
|
const lastStaked = beforeBlockNumber.add(bn(5))
|
|
await staking.setBlockNumber(lastStaked)
|
|
await approveAndStake({ staking, from: owner })
|
|
assertBn(await staking.totalStakedForAt(owner, beforeBlockNumber), bn(0), "Staked for at before staking should match")
|
|
assertBn(await staking.totalStakedForAt(owner, lastStaked), bn(DEFAULT_STAKE_AMOUNT), "Staked for after staking should match")
|
|
})
|
|
|
|
it('has correct "total staked at"', async () => {
|
|
const beforeBlockNumber = await staking.getBlockNumberPublic()
|
|
const lastStaked = beforeBlockNumber.add(bn(5))
|
|
await staking.setBlockNumber(lastStaked)
|
|
await approveAndStake({ staking, from: owner })
|
|
await approveAndStake({ staking, from: other })
|
|
assertBn(await staking.totalStakedAt(beforeBlockNumber), bn(0), "Staked for at before should match")
|
|
assertBn(await staking.totalStakedAt(lastStaked), bn(DEFAULT_STAKE_AMOUNT.mul(bn(2))), "Staked for at after staking should match")
|
|
})
|
|
|
|
it('fails to call totalStakedForAt with block number greater than max uint64', async () => {
|
|
await assertRevert(staking.totalStakedForAt(owner, MAX_UINT64.add(bn(1)))/*, STAKING_ERRORS.ERROR_BLOCKNUMBER_TOO_BIG*/)
|
|
})
|
|
|
|
it('fails to call totalStakedAt with block number greater than max uint64', async () => {
|
|
await assertRevert(staking.totalStakedAt(MAX_UINT64.add(bn(1)))/*, STAKING_ERRORS.ERROR_BLOCKNUMBER_TOO_BIG*/)
|
|
})
|
|
})
|
|
|
|
context('Bad Token', async () => {
|
|
let badStaking, badStakingAddress, badToken, badTokenAddress
|
|
beforeEach(async () => {
|
|
const initialAmount = DEFAULT_STAKE_AMOUNT.mul(bn(1000))
|
|
const tokenContract = await BadTokenMock.new(owner, initialAmount)
|
|
badToken = tokenContract
|
|
badTokenAddress = tokenContract.address
|
|
await badToken.mint(other, DEFAULT_STAKE_AMOUNT)
|
|
const stakingContract = await StakingMock.new(badTokenAddress)
|
|
badStaking = stakingContract
|
|
badStakingAddress = stakingContract.address
|
|
})
|
|
|
|
it('fails unstaking because of bad token', async () => {
|
|
// allow Staking app to move owner tokens
|
|
await badToken.approve(badStakingAddress, DEFAULT_STAKE_AMOUNT, { from: owner })
|
|
// stake tokens
|
|
await badStaking.stake(DEFAULT_STAKE_AMOUNT, EMPTY_DATA, { from: owner })
|
|
|
|
// unstake half of them, fails on token transfer
|
|
await assertRevert(badStaking.unstake(DEFAULT_STAKE_AMOUNT.div(bn(2)), EMPTY_DATA)/*, STAKING_ERRORS.ERROR_TOKEN_TRANSFER*/)
|
|
})
|
|
})
|
|
})
|