selfkey-token
Version:
The SelfKey Token is an ERC20 standard token that is used to fuel the SelfKey KYC dapps
192 lines (153 loc) • 7.09 kB
JavaScript
const SelfKeyCrowdsale = artifacts.require('./SelfKeyCrowdsale.sol')
const SelfKeyToken = artifacts.require('./SelfKeyToken.sol')
const assertThrows = require('./utils/assertThrows')
const { goal } = require('./utils/common')
contract('SelfKeyCrowdsale (Pre-sale)', accounts => {
const YEAR_IN_SECONDS = 31622400
const now = new Date().getTime() / 1000
const start = now + YEAR_IN_SECONDS
const end = start + YEAR_IN_SECONDS
const [
buyer3,
buyer2,
buyer,
verifier,
verifier2,
notVerifier,
notOwner
] = accounts.slice(3)
let presaleCrowdsale
let presaleToken
before(async () => {
presaleCrowdsale = await SelfKeyCrowdsale.new(start, end, goal)
const token = await presaleCrowdsale.token.call()
presaleToken = await SelfKeyToken.at(token)
})
it('does not allow end date to be earlier or the same than start date', async () => {
await assertThrows(SelfKeyCrowdsale.new(start, start, goal))
})
it('deploys successfully in pre-sale mode', async () => {
assert.isNotNull(presaleCrowdsale)
assert.isNotNull(presaleToken)
// verify owner is effectively added as a verifier
const ownerIsVerifier = await presaleCrowdsale.isVerifier.call(accounts[0])
assert.isTrue(ownerIsVerifier)
})
it('does not allow precommitments or verification calls from not verifiers', async () => {
const isVerifier = await presaleCrowdsale.isVerifier.call(notVerifier)
assert.isFalse(isVerifier)
await assertThrows(
presaleCrowdsale.addPrecommitment(buyer, 999, false, {
from: notVerifier
})
)
await assertThrows(presaleCrowdsale.verifyKYC(buyer, { from: notVerifier }))
})
it('allows adding new verifiers', async () => {
// add verifier
await presaleCrowdsale.addVerifier(verifier)
let isVerifier = await presaleCrowdsale.isVerifier.call(verifier)
assert.isTrue(isVerifier)
// add another verifier
await presaleCrowdsale.addVerifier(verifier2)
isVerifier = await presaleCrowdsale.isVerifier.call(verifier2)
assert.isTrue(isVerifier)
})
it('allows removal of verifiers', async () => {
let isVerifier = await presaleCrowdsale.isVerifier.call(verifier2)
assert.isTrue(isVerifier)
await presaleCrowdsale.removeVerifier(verifier2)
isVerifier = await presaleCrowdsale.isVerifier.call(verifier2)
assert.isFalse(isVerifier)
})
it('does not allow adding or removal of verifier by anyone other than the owner', async () => {
await assertThrows(presaleCrowdsale.addVerifier(buyer, { from: notOwner }))
await assertThrows(
presaleCrowdsale.removeVerifier(verifier, { from: notOwner })
)
})
// Offchain purchases
it("adds 'pre-commitments' for off-chain contributions, no vesting", async () => {
const allocation = web3.toWei(5, 'ether') // allocates 5 KEY
const balance1 = await presaleToken.balanceOf.call(buyer2)
// test non-timelocked pre-commitment
await presaleCrowdsale.addPrecommitment(buyer2, allocation, false, {
from: verifier
})
const balance2 = await presaleToken.balanceOf.call(buyer2)
assert.equal(balance2 - balance1, allocation)
})
it("adds 'pre-commitments' with vesting", async () => {
const allocation = web3.toWei(10, 'ether') // allocates 10 KEY
// const balance1 = await presaleToken.balanceOf.call(buyer3)
// test (half)timelocked pre-commitment
await presaleCrowdsale.addPrecommitment(buyer3, allocation, true, {
from: verifier
})
const balance2 = await presaleToken.balanceOf.call(buyer3)
// check half tokens are immediately transferred to participant's wallet
assert.equal(balance2.toNumber(), allocation / 2)
// check the other half is sent to the time-lock
const timelockAddress = await presaleCrowdsale.vestedTokens.call(buyer3)
const vestedBalance = await presaleToken.balanceOf.call(timelockAddress)
assert.equal(vestedBalance, allocation - allocation / 2)
// test failure on premature release of tokens
await assertThrows(presaleCrowdsale.releaseLock(buyer3))
})
it('adds vested tokens to already existing vested pre-sale participant', async () => {
const sender = buyer3
const allocation = web3.toWei(10, 'ether') // allocates 10 KEY
const timelockAddress = await presaleCrowdsale.vestedTokens.call(sender)
assert.notEqual(timelockAddress, 0x0)
const vestedBalance1 = await presaleToken.balanceOf.call(timelockAddress)
assert.isAbove(vestedBalance1.toNumber(), 0)
// test vested pre-commitment
const balance1 = await presaleToken.balanceOf.call(sender)
await presaleCrowdsale.addPrecommitment(sender, allocation, true)
const balance2 = await presaleToken.balanceOf.call(sender)
// check half tokens are immediately transferred to participant's wallet
assert.equal(balance2.toNumber() - balance1.toNumber(), allocation / 2)
// check the other half is sent to the time-lock
const vestedBalance2 = await presaleToken.balanceOf.call(timelockAddress)
assert.isAbove(vestedBalance2.toNumber(), vestedBalance1.toNumber())
// test failure on premature release of tokens
await assertThrows(presaleCrowdsale.releaseLock(sender))
})
it('does not allow any contributions before start time', async () => {
const sender = buyer
const sendAmount = web3.toWei(1, 'ether')
await presaleCrowdsale.verifyKYC(sender)
await assertThrows(
presaleCrowdsale.sendTransaction({ from: sender, value: sendAmount })
)
})
it('allows the updating of ETH price before sale starts', async () => {
// const rate1 = await presaleCrowdsale.rate.call()
const newEthPrice = 800
// Set new ETH price and get related attributes
await presaleCrowdsale.setEthPrice(newEthPrice)
const rate2 = await presaleCrowdsale.rate.call()
const keyPrice = await presaleCrowdsale.TOKEN_PRICE_THOUSANDTH.call()
// Calculate rates and caps to compare
const expectedRate = parseInt(newEthPrice * 1000 / keyPrice, 10)
assert.equal(expectedRate, rate2)
})
it('does not allow to set an ETH price equal to zero or negative number', async () => {
assertThrows(presaleCrowdsale.setEthPrice(0))
assertThrows(presaleCrowdsale.setEthPrice(-999))
})
it("does not release the founders' locked tokens too soon", async () => {
await assertThrows(presaleCrowdsale.releaseLockFounders1())
await assertThrows(presaleCrowdsale.releaseLockFounders2())
await assertThrows(presaleCrowdsale.releaseLockFoundation())
})
it('can change the start date if sale has not started', async () => {
const additionalTime = 9
const beforeStart = await presaleCrowdsale.startTime.call()
await presaleCrowdsale.setStartTime(beforeStart.toNumber() + additionalTime)
const laterStart = await presaleCrowdsale.startTime.call()
assert.equal(laterStart.toNumber(), beforeStart.toNumber() + additionalTime)
await assertThrows(presaleCrowdsale.setStartTime(now - 999))
await assertThrows(presaleCrowdsale.setStartTime(end + 1))
})
})