Merge pull request #581 from Shrugs/feat/minor-additions
Minor standards and cleanup additions.pull/597/head
commit
dd1fd0002a
@ -0,0 +1,5 @@ |
|||||||
|
# configure your infura api key (not technically required) |
||||||
|
INFURA_API_KEY= |
||||||
|
|
||||||
|
# change the mnemonic that your hd wallet is seeded with |
||||||
|
MNEMONIC= |
@ -0,0 +1,51 @@ |
|||||||
|
{ |
||||||
|
"extends" : [ |
||||||
|
"standard", |
||||||
|
"plugin:promise/recommended" |
||||||
|
], |
||||||
|
"plugins": [ |
||||||
|
"promise" |
||||||
|
], |
||||||
|
"env": { |
||||||
|
"browser" : true, |
||||||
|
"node" : true, |
||||||
|
"mocha" : true, |
||||||
|
"jest" : true |
||||||
|
}, |
||||||
|
"globals" : { |
||||||
|
"artifacts": false, |
||||||
|
"contract": false, |
||||||
|
"assert": false, |
||||||
|
"web3": false |
||||||
|
}, |
||||||
|
"rules": { |
||||||
|
|
||||||
|
// Strict mode |
||||||
|
"strict": [2, "global"], |
||||||
|
|
||||||
|
// Code style |
||||||
|
"indent": [2, 2], |
||||||
|
"quotes": [2, "single"], |
||||||
|
"semi": ["error", "always"], |
||||||
|
"space-before-function-paren": ["error", "always"], |
||||||
|
"no-use-before-define": 0, |
||||||
|
"eqeqeq": [2, "smart"], |
||||||
|
"dot-notation": [2, {"allowKeywords": true, "allowPattern": ""}], |
||||||
|
"no-redeclare": [2, {"builtinGlobals": true}], |
||||||
|
"no-trailing-spaces": [2, { "skipBlankLines": true }], |
||||||
|
"eol-last": 1, |
||||||
|
"comma-spacing": [2, {"before": false, "after": true}], |
||||||
|
"camelcase": [2, {"properties": "always"}], |
||||||
|
"no-mixed-spaces-and-tabs": [2, "smart-tabs"], |
||||||
|
"comma-dangle": [1, "always-multiline"], |
||||||
|
"no-dupe-args": 2, |
||||||
|
"no-dupe-keys": 2, |
||||||
|
"no-debugger": 0, |
||||||
|
"no-undef": 2, |
||||||
|
"object-curly-spacing": [2, "always"], |
||||||
|
"max-len": [2, 120, 2], |
||||||
|
"generator-star-spacing": ["error", "before"], |
||||||
|
"promise/avoid-new": 0, |
||||||
|
"promise/always-return": 0 |
||||||
|
} |
||||||
|
} |
@ -1,9 +1,35 @@ |
|||||||
*.swp |
*.swp |
||||||
*.swo |
*.swo |
||||||
node_modules/ |
|
||||||
build/ |
# Logs |
||||||
.DS_Store/ |
logs |
||||||
/coverage |
*.log |
||||||
coverage.json |
|
||||||
|
# Runtime data |
||||||
|
pids |
||||||
|
*.pid |
||||||
|
*.seed |
||||||
allFiredEvents |
allFiredEvents |
||||||
scTopics |
scTopics |
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul |
||||||
|
coverage |
||||||
|
coverage.json |
||||||
|
|
||||||
|
# node-waf configuration |
||||||
|
.lock-wscript |
||||||
|
|
||||||
|
# Dependency directory |
||||||
|
node_modules |
||||||
|
|
||||||
|
# Debug log from npm |
||||||
|
npm-debug.log |
||||||
|
|
||||||
|
# local env variables |
||||||
|
.env |
||||||
|
|
||||||
|
# truffle build directory |
||||||
|
build/ |
||||||
|
|
||||||
|
# lol macs |
||||||
|
.DS_Store/ |
||||||
|
@ -1,5 +1,9 @@ |
|||||||
// var Ownable = artifacts.require("ownership/Ownable.sol");
|
// var Ownable = artifacts.require("ownership/Ownable.sol");
|
||||||
|
|
||||||
|
// NOTE: Use this file to easily deploy the contracts you're writing.
|
||||||
|
// (but make sure to reset this file before committing
|
||||||
|
// with `git checkout HEAD -- migrations/2_deploy_contracts.js`)
|
||||||
|
|
||||||
module.exports = function (deployer) { |
module.exports = function (deployer) { |
||||||
// deployer.deploy(Ownable);
|
// deployer.deploy(Ownable);
|
||||||
}; |
}; |
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@ |
|||||||
|
{ |
||||||
|
"rules": { |
||||||
|
"no-unused-expressions": 0 |
||||||
|
} |
||||||
|
} |
@ -1,39 +0,0 @@ |
|||||||
'use strict' |
|
||||||
|
|
||||||
const EVMRevert = require('./helpers/EVMRevert.js') |
|
||||||
const BurnableTokenMock = artifacts.require("./helpers/BurnableTokenMock.sol") |
|
||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
const expect = require('chai').expect |
|
||||||
|
|
||||||
contract('BurnableToken', function (accounts) { |
|
||||||
let token |
|
||||||
let expectedTokenSupply = new BigNumber(999) |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
token = await BurnableTokenMock.new(accounts[0], 1000) |
|
||||||
}) |
|
||||||
|
|
||||||
it('owner should be able to burn tokens', async function () { |
|
||||||
const { logs } = await token.burn(1, { from: accounts[0] }) |
|
||||||
|
|
||||||
const balance = await token.balanceOf(accounts[0]) |
|
||||||
balance.should.be.bignumber.equal(expectedTokenSupply) |
|
||||||
|
|
||||||
const totalSupply = await token.totalSupply() |
|
||||||
totalSupply.should.be.bignumber.equal(expectedTokenSupply) |
|
||||||
|
|
||||||
const event = logs.find(e => e.event === 'Burn') |
|
||||||
expect(event).to.exist |
|
||||||
}) |
|
||||||
|
|
||||||
it('cannot burn more tokens than your balance', async function () { |
|
||||||
await token.burn(2000, { from: accounts[0] }) |
|
||||||
.should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
}) |
|
@ -0,0 +1,38 @@ |
|||||||
|
|
||||||
|
const EVMRevert = require('./helpers/EVMRevert.js'); |
||||||
|
const BurnableTokenMock = artifacts.require('./mocks/BurnableTokenMock.sol'); |
||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const expect = require('chai').expect; |
||||||
|
|
||||||
|
contract('BurnableToken', function (accounts) { |
||||||
|
let token; |
||||||
|
let expectedTokenSupply = new BigNumber(999); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
token = await BurnableTokenMock.new(accounts[0], 1000); |
||||||
|
}); |
||||||
|
|
||||||
|
it('owner should be able to burn tokens', async function () { |
||||||
|
const { logs } = await token.burn(1, { from: accounts[0] }); |
||||||
|
|
||||||
|
const balance = await token.balanceOf(accounts[0]); |
||||||
|
balance.should.be.bignumber.equal(expectedTokenSupply); |
||||||
|
|
||||||
|
const totalSupply = await token.totalSupply(); |
||||||
|
totalSupply.should.be.bignumber.equal(expectedTokenSupply); |
||||||
|
|
||||||
|
const event = logs.find(e => e.event === 'Burn'); |
||||||
|
expect(event).to.exist; |
||||||
|
}); |
||||||
|
|
||||||
|
it('cannot burn more tokens than your balance', async function () { |
||||||
|
await token.burn(2000, { from: accounts[0] }) |
||||||
|
.should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
}); |
@ -1,8 +1,8 @@ |
|||||||
'use strict'; |
|
||||||
import expectThrow from './helpers/expectThrow'; |
import expectThrow from './helpers/expectThrow'; |
||||||
import toPromise from './helpers/toPromise'; |
|
||||||
const CanReclaimToken = artifacts.require('../contracts/ownership/CanReclaimToken.sol'); |
const CanReclaimToken = artifacts.require('../contracts/ownership/CanReclaimToken.sol'); |
||||||
const BasicTokenMock = artifacts.require("./helpers/BasicTokenMock.sol"); |
const BasicTokenMock = artifacts.require('./mocks/BasicTokenMock.sol'); |
||||||
|
|
||||||
contract('CanReclaimToken', function (accounts) { |
contract('CanReclaimToken', function (accounts) { |
||||||
let token = null; |
let token = null; |
@ -1,96 +0,0 @@ |
|||||||
import ether from './helpers/ether' |
|
||||||
import {advanceBlock} from './helpers/advanceToBlock' |
|
||||||
import {increaseTimeTo, duration} from './helpers/increaseTime' |
|
||||||
import latestTime from './helpers/latestTime' |
|
||||||
import EVMRevert from './helpers/EVMRevert' |
|
||||||
|
|
||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
const CappedCrowdsale = artifacts.require('./helpers/CappedCrowdsaleImpl.sol') |
|
||||||
const MintableToken = artifacts.require('MintableToken') |
|
||||||
|
|
||||||
contract('CappedCrowdsale', function ([_, wallet]) { |
|
||||||
|
|
||||||
const rate = new BigNumber(1000) |
|
||||||
|
|
||||||
const cap = ether(300) |
|
||||||
const lessThanCap = ether(60) |
|
||||||
|
|
||||||
before(async function() { |
|
||||||
//Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
|
||||||
await advanceBlock() |
|
||||||
}) |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
this.startTime = latestTime() + duration.weeks(1); |
|
||||||
this.endTime = this.startTime + duration.weeks(1); |
|
||||||
|
|
||||||
this.crowdsale = await CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, cap) |
|
||||||
|
|
||||||
this.token = MintableToken.at(await this.crowdsale.token()) |
|
||||||
}) |
|
||||||
|
|
||||||
describe('creating a valid crowdsale', function () { |
|
||||||
|
|
||||||
it('should fail with zero cap', async function () { |
|
||||||
await CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0).should.be.rejectedWith(EVMRevert); |
|
||||||
}) |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
describe('accepting payments', function () { |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should accept payments within cap', async function () { |
|
||||||
await this.crowdsale.send(cap.minus(lessThanCap)).should.be.fulfilled |
|
||||||
await this.crowdsale.send(lessThanCap).should.be.fulfilled |
|
||||||
}) |
|
||||||
|
|
||||||
it('should reject payments outside cap', async function () { |
|
||||||
await this.crowdsale.send(cap) |
|
||||||
await this.crowdsale.send(1).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should reject payments that exceed cap', async function () { |
|
||||||
await this.crowdsale.send(cap.plus(1)).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
||||||
|
|
||||||
describe('ending', function () { |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should not be ended if under cap', async function () { |
|
||||||
let hasEnded = await this.crowdsale.hasEnded() |
|
||||||
hasEnded.should.equal(false) |
|
||||||
await this.crowdsale.send(lessThanCap) |
|
||||||
hasEnded = await this.crowdsale.hasEnded() |
|
||||||
hasEnded.should.equal(false) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should not be ended if just under cap', async function () { |
|
||||||
await this.crowdsale.send(cap.minus(1)) |
|
||||||
let hasEnded = await this.crowdsale.hasEnded() |
|
||||||
hasEnded.should.equal(false) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should be ended if cap reached', async function () { |
|
||||||
await this.crowdsale.send(cap) |
|
||||||
let hasEnded = await this.crowdsale.hasEnded() |
|
||||||
hasEnded.should.equal(true) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
@ -0,0 +1,88 @@ |
|||||||
|
import ether from './helpers/ether'; |
||||||
|
import { advanceBlock } from './helpers/advanceToBlock'; |
||||||
|
import { increaseTimeTo, duration } from './helpers/increaseTime'; |
||||||
|
import latestTime from './helpers/latestTime'; |
||||||
|
import EVMRevert from './helpers/EVMRevert'; |
||||||
|
|
||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const CappedCrowdsale = artifacts.require('./mocks/CappedCrowdsaleImpl.sol'); |
||||||
|
const MintableToken = artifacts.require('MintableToken'); |
||||||
|
|
||||||
|
contract('CappedCrowdsale', function ([_, wallet]) { |
||||||
|
const rate = new BigNumber(1000); |
||||||
|
|
||||||
|
const cap = ether(300); |
||||||
|
const lessThanCap = ether(60); |
||||||
|
|
||||||
|
before(async function () { |
||||||
|
// Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
||||||
|
await advanceBlock(); |
||||||
|
}); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
this.startTime = latestTime() + duration.weeks(1); |
||||||
|
this.endTime = this.startTime + duration.weeks(1); |
||||||
|
|
||||||
|
this.crowdsale = await CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, cap); |
||||||
|
|
||||||
|
this.token = MintableToken.at(await this.crowdsale.token()); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('creating a valid crowdsale', function () { |
||||||
|
it('should fail with zero cap', async function () { |
||||||
|
await CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('accepting payments', function () { |
||||||
|
beforeEach(async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should accept payments within cap', async function () { |
||||||
|
await this.crowdsale.send(cap.minus(lessThanCap)).should.be.fulfilled; |
||||||
|
await this.crowdsale.send(lessThanCap).should.be.fulfilled; |
||||||
|
}); |
||||||
|
|
||||||
|
it('should reject payments outside cap', async function () { |
||||||
|
await this.crowdsale.send(cap); |
||||||
|
await this.crowdsale.send(1).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should reject payments that exceed cap', async function () { |
||||||
|
await this.crowdsale.send(cap.plus(1)).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('ending', function () { |
||||||
|
beforeEach(async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should not be ended if under cap', async function () { |
||||||
|
let hasEnded = await this.crowdsale.hasEnded(); |
||||||
|
hasEnded.should.equal(false); |
||||||
|
await this.crowdsale.send(lessThanCap); |
||||||
|
hasEnded = await this.crowdsale.hasEnded(); |
||||||
|
hasEnded.should.equal(false); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should not be ended if just under cap', async function () { |
||||||
|
await this.crowdsale.send(cap.minus(1)); |
||||||
|
let hasEnded = await this.crowdsale.hasEnded(); |
||||||
|
hasEnded.should.equal(false); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should be ended if cap reached', async function () { |
||||||
|
await this.crowdsale.send(cap); |
||||||
|
let hasEnded = await this.crowdsale.hasEnded(); |
||||||
|
hasEnded.should.equal(true); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
@ -1,4 +1,4 @@ |
|||||||
'use strict'; |
|
||||||
const assertRevert = require('./helpers/assertRevert'); |
const assertRevert = require('./helpers/assertRevert'); |
||||||
|
|
||||||
var Claimable = artifacts.require('../contracts/ownership/Claimable.sol'); |
var Claimable = artifacts.require('../contracts/ownership/Claimable.sol'); |
@ -1,152 +0,0 @@ |
|||||||
import ether from './helpers/ether' |
|
||||||
import {advanceBlock} from './helpers/advanceToBlock' |
|
||||||
import {increaseTimeTo, duration} from './helpers/increaseTime' |
|
||||||
import latestTime from './helpers/latestTime' |
|
||||||
import EVMRevert from './helpers/EVMRevert' |
|
||||||
|
|
||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
const should = require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
const Crowdsale = artifacts.require('Crowdsale') |
|
||||||
const MintableToken = artifacts.require('MintableToken') |
|
||||||
|
|
||||||
contract('Crowdsale', function ([_, investor, wallet, purchaser]) { |
|
||||||
|
|
||||||
const rate = new BigNumber(1000) |
|
||||||
const value = ether(42) |
|
||||||
|
|
||||||
const expectedTokenAmount = rate.mul(value) |
|
||||||
|
|
||||||
before(async function() { |
|
||||||
//Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
|
||||||
await advanceBlock() |
|
||||||
}) |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
this.startTime = latestTime() + duration.weeks(1); |
|
||||||
this.endTime = this.startTime + duration.weeks(1); |
|
||||||
this.afterEndTime = this.endTime + duration.seconds(1) |
|
||||||
|
|
||||||
|
|
||||||
this.crowdsale = await Crowdsale.new(this.startTime, this.endTime, rate, wallet) |
|
||||||
|
|
||||||
this.token = MintableToken.at(await this.crowdsale.token()) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should be token owner', async function () { |
|
||||||
const owner = await this.token.owner() |
|
||||||
owner.should.equal(this.crowdsale.address) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should be ended only after end', async function () { |
|
||||||
let ended = await this.crowdsale.hasEnded() |
|
||||||
ended.should.equal(false) |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
ended = await this.crowdsale.hasEnded() |
|
||||||
ended.should.equal(true) |
|
||||||
}) |
|
||||||
|
|
||||||
describe('accepting payments', function () { |
|
||||||
|
|
||||||
it('should reject payments before start', async function () { |
|
||||||
await this.crowdsale.send(value).should.be.rejectedWith(EVMRevert) |
|
||||||
await this.crowdsale.buyTokens(investor, {from: purchaser, value: value}).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should accept payments after start', async function () { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
await this.crowdsale.send(value).should.be.fulfilled |
|
||||||
await this.crowdsale.buyTokens(investor, {value: value, from: purchaser}).should.be.fulfilled |
|
||||||
}) |
|
||||||
|
|
||||||
it('should reject payments after end', async function () { |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
await this.crowdsale.send(value).should.be.rejectedWith(EVMRevert) |
|
||||||
await this.crowdsale.buyTokens(investor, {value: value, from: purchaser}).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
||||||
|
|
||||||
describe('high-level purchase', function () { |
|
||||||
|
|
||||||
beforeEach(async function() { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should log purchase', async function () { |
|
||||||
const {logs} = await this.crowdsale.sendTransaction({value: value, from: investor}) |
|
||||||
|
|
||||||
const event = logs.find(e => e.event === 'TokenPurchase') |
|
||||||
|
|
||||||
should.exist(event) |
|
||||||
event.args.purchaser.should.equal(investor) |
|
||||||
event.args.beneficiary.should.equal(investor) |
|
||||||
event.args.value.should.be.bignumber.equal(value) |
|
||||||
event.args.amount.should.be.bignumber.equal(expectedTokenAmount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should increase totalSupply', async function () { |
|
||||||
await this.crowdsale.send(value) |
|
||||||
const totalSupply = await this.token.totalSupply() |
|
||||||
totalSupply.should.be.bignumber.equal(expectedTokenAmount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should assign tokens to sender', async function () { |
|
||||||
await this.crowdsale.sendTransaction({value: value, from: investor}) |
|
||||||
let balance = await this.token.balanceOf(investor); |
|
||||||
balance.should.be.bignumber.equal(expectedTokenAmount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should forward funds to wallet', async function () { |
|
||||||
const pre = web3.eth.getBalance(wallet) |
|
||||||
await this.crowdsale.sendTransaction({value, from: investor}) |
|
||||||
const post = web3.eth.getBalance(wallet) |
|
||||||
post.minus(pre).should.be.bignumber.equal(value) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
||||||
|
|
||||||
describe('low-level purchase', function () { |
|
||||||
|
|
||||||
beforeEach(async function() { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should log purchase', async function () { |
|
||||||
const {logs} = await this.crowdsale.buyTokens(investor, {value: value, from: purchaser}) |
|
||||||
|
|
||||||
const event = logs.find(e => e.event === 'TokenPurchase') |
|
||||||
|
|
||||||
should.exist(event) |
|
||||||
event.args.purchaser.should.equal(purchaser) |
|
||||||
event.args.beneficiary.should.equal(investor) |
|
||||||
event.args.value.should.be.bignumber.equal(value) |
|
||||||
event.args.amount.should.be.bignumber.equal(expectedTokenAmount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should increase totalSupply', async function () { |
|
||||||
await this.crowdsale.buyTokens(investor, {value, from: purchaser}) |
|
||||||
const totalSupply = await this.token.totalSupply() |
|
||||||
totalSupply.should.be.bignumber.equal(expectedTokenAmount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should assign tokens to beneficiary', async function () { |
|
||||||
await this.crowdsale.buyTokens(investor, {value, from: purchaser}) |
|
||||||
const balance = await this.token.balanceOf(investor) |
|
||||||
balance.should.be.bignumber.equal(expectedTokenAmount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should forward funds to wallet', async function () { |
|
||||||
const pre = web3.eth.getBalance(wallet) |
|
||||||
await this.crowdsale.buyTokens(investor, {value, from: purchaser}) |
|
||||||
const post = web3.eth.getBalance(wallet) |
|
||||||
post.minus(pre).should.be.bignumber.equal(value) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
@ -0,0 +1,143 @@ |
|||||||
|
import ether from './helpers/ether'; |
||||||
|
import { advanceBlock } from './helpers/advanceToBlock'; |
||||||
|
import { increaseTimeTo, duration } from './helpers/increaseTime'; |
||||||
|
import latestTime from './helpers/latestTime'; |
||||||
|
import EVMRevert from './helpers/EVMRevert'; |
||||||
|
|
||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
const should = require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const Crowdsale = artifacts.require('Crowdsale'); |
||||||
|
const MintableToken = artifacts.require('MintableToken'); |
||||||
|
|
||||||
|
contract('Crowdsale', function ([_, investor, wallet, purchaser]) { |
||||||
|
const rate = new BigNumber(1000); |
||||||
|
const value = ether(42); |
||||||
|
|
||||||
|
const expectedTokenAmount = rate.mul(value); |
||||||
|
|
||||||
|
before(async function () { |
||||||
|
// Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
||||||
|
await advanceBlock(); |
||||||
|
}); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
this.startTime = latestTime() + duration.weeks(1); |
||||||
|
this.endTime = this.startTime + duration.weeks(1); |
||||||
|
this.afterEndTime = this.endTime + duration.seconds(1); |
||||||
|
|
||||||
|
this.crowdsale = await Crowdsale.new(this.startTime, this.endTime, rate, wallet); |
||||||
|
|
||||||
|
this.token = MintableToken.at(await this.crowdsale.token()); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should be token owner', async function () { |
||||||
|
const owner = await this.token.owner(); |
||||||
|
owner.should.equal(this.crowdsale.address); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should be ended only after end', async function () { |
||||||
|
let ended = await this.crowdsale.hasEnded(); |
||||||
|
ended.should.equal(false); |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
ended = await this.crowdsale.hasEnded(); |
||||||
|
ended.should.equal(true); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('accepting payments', function () { |
||||||
|
it('should reject payments before start', async function () { |
||||||
|
await this.crowdsale.send(value).should.be.rejectedWith(EVMRevert); |
||||||
|
await this.crowdsale.buyTokens(investor, { from: purchaser, value: value }).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should accept payments after start', async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
await this.crowdsale.send(value).should.be.fulfilled; |
||||||
|
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }).should.be.fulfilled; |
||||||
|
}); |
||||||
|
|
||||||
|
it('should reject payments after end', async function () { |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
await this.crowdsale.send(value).should.be.rejectedWith(EVMRevert); |
||||||
|
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('high-level purchase', function () { |
||||||
|
beforeEach(async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should log purchase', async function () { |
||||||
|
const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); |
||||||
|
|
||||||
|
const event = logs.find(e => e.event === 'TokenPurchase'); |
||||||
|
|
||||||
|
should.exist(event); |
||||||
|
event.args.purchaser.should.equal(investor); |
||||||
|
event.args.beneficiary.should.equal(investor); |
||||||
|
event.args.value.should.be.bignumber.equal(value); |
||||||
|
event.args.amount.should.be.bignumber.equal(expectedTokenAmount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should increase totalSupply', async function () { |
||||||
|
await this.crowdsale.send(value); |
||||||
|
const totalSupply = await this.token.totalSupply(); |
||||||
|
totalSupply.should.be.bignumber.equal(expectedTokenAmount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should assign tokens to sender', async function () { |
||||||
|
await this.crowdsale.sendTransaction({ value: value, from: investor }); |
||||||
|
let balance = await this.token.balanceOf(investor); |
||||||
|
balance.should.be.bignumber.equal(expectedTokenAmount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should forward funds to wallet', async function () { |
||||||
|
const pre = web3.eth.getBalance(wallet); |
||||||
|
await this.crowdsale.sendTransaction({ value, from: investor }); |
||||||
|
const post = web3.eth.getBalance(wallet); |
||||||
|
post.minus(pre).should.be.bignumber.equal(value); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('low-level purchase', function () { |
||||||
|
beforeEach(async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should log purchase', async function () { |
||||||
|
const { logs } = await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }); |
||||||
|
|
||||||
|
const event = logs.find(e => e.event === 'TokenPurchase'); |
||||||
|
|
||||||
|
should.exist(event); |
||||||
|
event.args.purchaser.should.equal(purchaser); |
||||||
|
event.args.beneficiary.should.equal(investor); |
||||||
|
event.args.value.should.be.bignumber.equal(value); |
||||||
|
event.args.amount.should.be.bignumber.equal(expectedTokenAmount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should increase totalSupply', async function () { |
||||||
|
await this.crowdsale.buyTokens(investor, { value, from: purchaser }); |
||||||
|
const totalSupply = await this.token.totalSupply(); |
||||||
|
totalSupply.should.be.bignumber.equal(expectedTokenAmount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should assign tokens to beneficiary', async function () { |
||||||
|
await this.crowdsale.buyTokens(investor, { value, from: purchaser }); |
||||||
|
const balance = await this.token.balanceOf(investor); |
||||||
|
balance.should.be.bignumber.equal(expectedTokenAmount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should forward funds to wallet', async function () { |
||||||
|
const pre = web3.eth.getBalance(wallet); |
||||||
|
await this.crowdsale.buyTokens(investor, { value, from: purchaser }); |
||||||
|
const post = web3.eth.getBalance(wallet); |
||||||
|
post.minus(pre).should.be.bignumber.equal(value); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
@ -1,63 +0,0 @@ |
|||||||
import {advanceBlock} from './helpers/advanceToBlock' |
|
||||||
import {increaseTimeTo, duration} from './helpers/increaseTime' |
|
||||||
import latestTime from './helpers/latestTime' |
|
||||||
import EVMRevert from './helpers/EVMRevert' |
|
||||||
|
|
||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
const should = require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
const FinalizableCrowdsale = artifacts.require('./helpers/FinalizableCrowdsaleImpl.sol') |
|
||||||
const MintableToken = artifacts.require('MintableToken') |
|
||||||
|
|
||||||
contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) { |
|
||||||
|
|
||||||
const rate = new BigNumber(1000) |
|
||||||
|
|
||||||
before(async function() { |
|
||||||
//Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
|
||||||
await advanceBlock() |
|
||||||
}) |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
this.startTime = latestTime() + duration.weeks(1) |
|
||||||
this.endTime = this.startTime + duration.weeks(1) |
|
||||||
this.afterEndTime = this.endTime + duration.seconds(1) |
|
||||||
|
|
||||||
|
|
||||||
this.crowdsale = await FinalizableCrowdsale.new(this.startTime, this.endTime, rate, wallet, {from: owner}) |
|
||||||
|
|
||||||
this.token = MintableToken.at(await this.crowdsale.token()) |
|
||||||
}) |
|
||||||
|
|
||||||
it('cannot be finalized before ending', async function () { |
|
||||||
await this.crowdsale.finalize({from: owner}).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('cannot be finalized by third party after ending', async function () { |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
await this.crowdsale.finalize({from: thirdparty}).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('can be finalized by owner after ending', async function () { |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
await this.crowdsale.finalize({from: owner}).should.be.fulfilled |
|
||||||
}) |
|
||||||
|
|
||||||
it('cannot be finalized twice', async function () { |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
await this.crowdsale.finalize({from: owner}) |
|
||||||
await this.crowdsale.finalize({from: owner}).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('logs finalized', async function () { |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
const {logs} = await this.crowdsale.finalize({from: owner}) |
|
||||||
const event = logs.find(e => e.event === 'Finalized') |
|
||||||
should.exist(event) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
@ -0,0 +1,60 @@ |
|||||||
|
import { advanceBlock } from './helpers/advanceToBlock'; |
||||||
|
import { increaseTimeTo, duration } from './helpers/increaseTime'; |
||||||
|
import latestTime from './helpers/latestTime'; |
||||||
|
import EVMRevert from './helpers/EVMRevert'; |
||||||
|
|
||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
const should = require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const FinalizableCrowdsale = artifacts.require('./mocks/FinalizableCrowdsaleImpl.sol'); |
||||||
|
const MintableToken = artifacts.require('MintableToken'); |
||||||
|
|
||||||
|
contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) { |
||||||
|
const rate = new BigNumber(1000); |
||||||
|
|
||||||
|
before(async function () { |
||||||
|
// Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
||||||
|
await advanceBlock(); |
||||||
|
}); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
this.startTime = latestTime() + duration.weeks(1); |
||||||
|
this.endTime = this.startTime + duration.weeks(1); |
||||||
|
this.afterEndTime = this.endTime + duration.seconds(1); |
||||||
|
|
||||||
|
this.crowdsale = await FinalizableCrowdsale.new(this.startTime, this.endTime, rate, wallet, { from: owner }); |
||||||
|
|
||||||
|
this.token = MintableToken.at(await this.crowdsale.token()); |
||||||
|
}); |
||||||
|
|
||||||
|
it('cannot be finalized before ending', async function () { |
||||||
|
await this.crowdsale.finalize({ from: owner }).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('cannot be finalized by third party after ending', async function () { |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
await this.crowdsale.finalize({ from: thirdparty }).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('can be finalized by owner after ending', async function () { |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
await this.crowdsale.finalize({ from: owner }).should.be.fulfilled; |
||||||
|
}); |
||||||
|
|
||||||
|
it('cannot be finalized twice', async function () { |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
await this.crowdsale.finalize({ from: owner }); |
||||||
|
await this.crowdsale.finalize({ from: owner }).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('logs finalized', async function () { |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
const { logs } = await this.crowdsale.finalize({ from: owner }); |
||||||
|
const event = logs.find(e => e.event === 'Finalized'); |
||||||
|
should.exist(event); |
||||||
|
}); |
||||||
|
}); |
@ -1,6 +1,6 @@ |
|||||||
'use strict'; |
|
||||||
import expectThrow from './helpers/expectThrow'; |
import expectThrow from './helpers/expectThrow'; |
||||||
import toPromise from './helpers/toPromise'; |
|
||||||
const Ownable = artifacts.require('../contracts/ownership/Ownable.sol'); |
const Ownable = artifacts.require('../contracts/ownership/Ownable.sol'); |
||||||
const HasNoContracts = artifacts.require( |
const HasNoContracts = artifacts.require( |
||||||
'../contracts/ownership/HasNoContracts.sol', |
'../contracts/ownership/HasNoContracts.sol', |
@ -1,15 +1,14 @@ |
|||||||
'use strict'; |
|
||||||
import expectThrow from './helpers/expectThrow'; |
import expectThrow from './helpers/expectThrow'; |
||||||
import toPromise from './helpers/toPromise'; |
import toPromise from './helpers/toPromise'; |
||||||
const HasNoEther = artifacts.require('../contracts/lifecycle/HasNoEther.sol'); |
const HasNoEtherTest = artifacts.require('../mocks/HasNoEtherTest.sol'); |
||||||
const HasNoEtherTest = artifacts.require('../helpers/HasNoEtherTest.sol'); |
const ForceEther = artifacts.require('../mocks/ForceEther.sol'); |
||||||
const ForceEther = artifacts.require('../helpers/ForceEther.sol'); |
|
||||||
|
|
||||||
contract('HasNoEther', function (accounts) { |
contract('HasNoEther', function (accounts) { |
||||||
const amount = web3.toWei('1', 'ether'); |
const amount = web3.toWei('1', 'ether'); |
||||||
|
|
||||||
it('should be constructorable', async function () { |
it('should be constructorable', async function () { |
||||||
let hasNoEther = await HasNoEtherTest.new(); |
await HasNoEtherTest.new(); |
||||||
}); |
}); |
||||||
|
|
||||||
it('should not accept ether in constructor', async function () { |
it('should not accept ether in constructor', async function () { |
@ -1,8 +1,8 @@ |
|||||||
'use strict'; |
|
||||||
import expectThrow from './helpers/expectThrow'; |
import expectThrow from './helpers/expectThrow'; |
||||||
import toPromise from './helpers/toPromise'; |
|
||||||
const HasNoTokens = artifacts.require('../contracts/lifecycle/HasNoTokens.sol'); |
const HasNoTokens = artifacts.require('../contracts/lifecycle/HasNoTokens.sol'); |
||||||
const ERC23TokenMock = artifacts.require('./helpers/ERC23TokenMock.sol'); |
const ERC23TokenMock = artifacts.require('./mocks/ERC23TokenMock.sol'); |
||||||
|
|
||||||
contract('HasNoTokens', function (accounts) { |
contract('HasNoTokens', function (accounts) { |
||||||
let hasNoTokens = null; |
let hasNoTokens = null; |
@ -1,61 +0,0 @@ |
|||||||
'use strict'; |
|
||||||
|
|
||||||
var LimitBalanceMock = artifacts.require('helpers/LimitBalanceMock.sol'); |
|
||||||
const assertRevert = require('./helpers/assertRevert'); |
|
||||||
|
|
||||||
contract('LimitBalance', function(accounts) { |
|
||||||
let lb; |
|
||||||
|
|
||||||
beforeEach(async function() { |
|
||||||
lb = await LimitBalanceMock.new(); |
|
||||||
}); |
|
||||||
|
|
||||||
let LIMIT = 1000; |
|
||||||
|
|
||||||
it('should expose limit', async function() { |
|
||||||
let limit = await lb.limit(); |
|
||||||
assert.equal(limit, LIMIT); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should allow sending below limit', async function() { |
|
||||||
let amount = 1; |
|
||||||
await lb.limitedDeposit({value: amount}); |
|
||||||
|
|
||||||
assert.equal(web3.eth.getBalance(lb.address), amount); |
|
||||||
}); |
|
||||||
|
|
||||||
it('shouldnt allow sending above limit', async function() { |
|
||||||
let amount = 1110; |
|
||||||
try { |
|
||||||
await lb.limitedDeposit({value: amount}); |
|
||||||
assert.fail('should have thrown before'); |
|
||||||
} catch(error) { |
|
||||||
assertRevert(error); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
it('should allow multiple sends below limit', async function() { |
|
||||||
let amount = 500; |
|
||||||
await lb.limitedDeposit({value: amount}); |
|
||||||
|
|
||||||
assert.equal(web3.eth.getBalance(lb.address), amount); |
|
||||||
|
|
||||||
await lb.limitedDeposit({value: amount}); |
|
||||||
assert.equal(web3.eth.getBalance(lb.address), amount*2); |
|
||||||
}); |
|
||||||
|
|
||||||
it('shouldnt allow multiple sends above limit', async function() { |
|
||||||
let amount = 500; |
|
||||||
await lb.limitedDeposit({value: amount}); |
|
||||||
|
|
||||||
assert.equal(web3.eth.getBalance(lb.address), amount); |
|
||||||
|
|
||||||
try { |
|
||||||
await lb.limitedDeposit({value: amount+1}); |
|
||||||
assert.fail('should have thrown before'); |
|
||||||
} catch(error) { |
|
||||||
assertRevert(error); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
@ -0,0 +1,59 @@ |
|||||||
|
|
||||||
|
var LimitBalanceMock = artifacts.require('mocks/LimitBalanceMock.sol'); |
||||||
|
const assertRevert = require('./helpers/assertRevert'); |
||||||
|
|
||||||
|
contract('LimitBalance', function (accounts) { |
||||||
|
let lb; |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
lb = await LimitBalanceMock.new(); |
||||||
|
}); |
||||||
|
|
||||||
|
let LIMIT = 1000; |
||||||
|
|
||||||
|
it('should expose limit', async function () { |
||||||
|
let limit = await lb.limit(); |
||||||
|
assert.equal(limit, LIMIT); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should allow sending below limit', async function () { |
||||||
|
let amount = 1; |
||||||
|
await lb.limitedDeposit({ value: amount }); |
||||||
|
|
||||||
|
assert.equal(web3.eth.getBalance(lb.address), amount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('shouldnt allow sending above limit', async function () { |
||||||
|
let amount = 1110; |
||||||
|
try { |
||||||
|
await lb.limitedDeposit({ value: amount }); |
||||||
|
assert.fail('should have thrown before'); |
||||||
|
} catch (error) { |
||||||
|
assertRevert(error); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
it('should allow multiple sends below limit', async function () { |
||||||
|
let amount = 500; |
||||||
|
await lb.limitedDeposit({ value: amount }); |
||||||
|
|
||||||
|
assert.equal(web3.eth.getBalance(lb.address), amount); |
||||||
|
|
||||||
|
await lb.limitedDeposit({ value: amount }); |
||||||
|
assert.equal(web3.eth.getBalance(lb.address), amount * 2); |
||||||
|
}); |
||||||
|
|
||||||
|
it('shouldnt allow multiple sends above limit', async function () { |
||||||
|
let amount = 500; |
||||||
|
await lb.limitedDeposit({ value: amount }); |
||||||
|
|
||||||
|
assert.equal(web3.eth.getBalance(lb.address), amount); |
||||||
|
|
||||||
|
try { |
||||||
|
await lb.limitedDeposit({ value: amount + 1 }); |
||||||
|
assert.fail('should have thrown before'); |
||||||
|
} catch (error) { |
||||||
|
assertRevert(error); |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
@ -1,4 +1,4 @@ |
|||||||
'use strict'; |
|
||||||
import expectThrow from './helpers/expectThrow'; |
import expectThrow from './helpers/expectThrow'; |
||||||
const ReentrancyMock = artifacts.require('./helper/ReentrancyMock.sol'); |
const ReentrancyMock = artifacts.require('./helper/ReentrancyMock.sol'); |
||||||
const ReentrancyAttack = artifacts.require('./helper/ReentrancyAttack.sol'); |
const ReentrancyAttack = artifacts.require('./helper/ReentrancyAttack.sol'); |
@ -1,61 +0,0 @@ |
|||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
import ether from './helpers/ether' |
|
||||||
import EVMRevert from './helpers/EVMRevert' |
|
||||||
|
|
||||||
const RefundVault = artifacts.require('RefundVault') |
|
||||||
|
|
||||||
contract('RefundVault', function ([_, owner, wallet, investor]) { |
|
||||||
|
|
||||||
const value = ether(42) |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
this.vault = await RefundVault.new(wallet, {from: owner}) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should accept contributions', async function () { |
|
||||||
await this.vault.deposit(investor, {value, from: owner}).should.be.fulfilled |
|
||||||
}) |
|
||||||
|
|
||||||
it('should not refund contribution during active state', async function () { |
|
||||||
await this.vault.deposit(investor, {value, from: owner}) |
|
||||||
await this.vault.refund(investor).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('only owner can enter refund mode', async function () { |
|
||||||
await this.vault.enableRefunds({from: _}).should.be.rejectedWith(EVMRevert) |
|
||||||
await this.vault.enableRefunds({from: owner}).should.be.fulfilled |
|
||||||
}) |
|
||||||
|
|
||||||
it('should refund contribution after entering refund mode', async function () { |
|
||||||
await this.vault.deposit(investor, {value, from: owner}) |
|
||||||
await this.vault.enableRefunds({from: owner}) |
|
||||||
|
|
||||||
const pre = web3.eth.getBalance(investor) |
|
||||||
await this.vault.refund(investor) |
|
||||||
const post = web3.eth.getBalance(investor) |
|
||||||
|
|
||||||
post.minus(pre).should.be.bignumber.equal(value) |
|
||||||
}) |
|
||||||
|
|
||||||
it('only owner can close', async function () { |
|
||||||
await this.vault.close({from: _}).should.be.rejectedWith(EVMRevert) |
|
||||||
await this.vault.close({from: owner}).should.be.fulfilled |
|
||||||
}) |
|
||||||
|
|
||||||
it('should forward funds to wallet after closing', async function () { |
|
||||||
await this.vault.deposit(investor, {value, from: owner}) |
|
||||||
|
|
||||||
const pre = web3.eth.getBalance(wallet) |
|
||||||
await this.vault.close({from: owner}) |
|
||||||
const post = web3.eth.getBalance(wallet) |
|
||||||
|
|
||||||
post.minus(pre).should.be.bignumber.equal(value) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
@ -0,0 +1,59 @@ |
|||||||
|
import ether from './helpers/ether'; |
||||||
|
import EVMRevert from './helpers/EVMRevert'; |
||||||
|
|
||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const RefundVault = artifacts.require('RefundVault'); |
||||||
|
|
||||||
|
contract('RefundVault', function ([_, owner, wallet, investor]) { |
||||||
|
const value = ether(42); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
this.vault = await RefundVault.new(wallet, { from: owner }); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should accept contributions', async function () { |
||||||
|
await this.vault.deposit(investor, { value, from: owner }).should.be.fulfilled; |
||||||
|
}); |
||||||
|
|
||||||
|
it('should not refund contribution during active state', async function () { |
||||||
|
await this.vault.deposit(investor, { value, from: owner }); |
||||||
|
await this.vault.refund(investor).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('only owner can enter refund mode', async function () { |
||||||
|
await this.vault.enableRefunds({ from: _ }).should.be.rejectedWith(EVMRevert); |
||||||
|
await this.vault.enableRefunds({ from: owner }).should.be.fulfilled; |
||||||
|
}); |
||||||
|
|
||||||
|
it('should refund contribution after entering refund mode', async function () { |
||||||
|
await this.vault.deposit(investor, { value, from: owner }); |
||||||
|
await this.vault.enableRefunds({ from: owner }); |
||||||
|
|
||||||
|
const pre = web3.eth.getBalance(investor); |
||||||
|
await this.vault.refund(investor); |
||||||
|
const post = web3.eth.getBalance(investor); |
||||||
|
|
||||||
|
post.minus(pre).should.be.bignumber.equal(value); |
||||||
|
}); |
||||||
|
|
||||||
|
it('only owner can close', async function () { |
||||||
|
await this.vault.close({ from: _ }).should.be.rejectedWith(EVMRevert); |
||||||
|
await this.vault.close({ from: owner }).should.be.fulfilled; |
||||||
|
}); |
||||||
|
|
||||||
|
it('should forward funds to wallet after closing', async function () { |
||||||
|
await this.vault.deposit(investor, { value, from: owner }); |
||||||
|
|
||||||
|
const pre = web3.eth.getBalance(wallet); |
||||||
|
await this.vault.close({ from: owner }); |
||||||
|
const post = web3.eth.getBalance(wallet); |
||||||
|
|
||||||
|
post.minus(pre).should.be.bignumber.equal(value); |
||||||
|
}); |
||||||
|
}); |
@ -1,83 +0,0 @@ |
|||||||
import ether from './helpers/ether' |
|
||||||
import {advanceBlock} from './helpers/advanceToBlock' |
|
||||||
import {increaseTimeTo, duration} from './helpers/increaseTime' |
|
||||||
import latestTime from './helpers/latestTime' |
|
||||||
import EVMRevert from './helpers/EVMRevert' |
|
||||||
|
|
||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
const RefundableCrowdsale = artifacts.require('./helpers/RefundableCrowdsaleImpl.sol') |
|
||||||
|
|
||||||
contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) { |
|
||||||
|
|
||||||
const rate = new BigNumber(1000) |
|
||||||
const goal = ether(800) |
|
||||||
const lessThanGoal = ether(750) |
|
||||||
|
|
||||||
before(async function() { |
|
||||||
//Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
|
||||||
await advanceBlock() |
|
||||||
}) |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
this.startTime = latestTime() + duration.weeks(1) |
|
||||||
this.endTime = this.startTime + duration.weeks(1) |
|
||||||
this.afterEndTime = this.endTime + duration.seconds(1) |
|
||||||
|
|
||||||
this.crowdsale = await RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, goal, {from: owner}) |
|
||||||
}) |
|
||||||
|
|
||||||
describe('creating a valid crowdsale', function () { |
|
||||||
|
|
||||||
it('should fail with zero goal', async function () { |
|
||||||
await RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, {from: owner}).should.be.rejectedWith(EVMRevert); |
|
||||||
}) |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
it('should deny refunds before end', async function () { |
|
||||||
await this.crowdsale.claimRefund({from: investor}).should.be.rejectedWith(EVMRevert) |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
await this.crowdsale.claimRefund({from: investor}).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should deny refunds after end if goal was reached', async function () { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
await this.crowdsale.sendTransaction({value: goal, from: investor}) |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
await this.crowdsale.claimRefund({from: investor}).should.be.rejectedWith(EVMRevert) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should allow refunds after end if goal was not reached', async function () { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
await this.crowdsale.sendTransaction({value: lessThanGoal, from: investor}) |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
|
|
||||||
await this.crowdsale.finalize({from: owner}) |
|
||||||
|
|
||||||
const pre = web3.eth.getBalance(investor) |
|
||||||
await this.crowdsale.claimRefund({from: investor, gasPrice: 0}) |
|
||||||
.should.be.fulfilled |
|
||||||
const post = web3.eth.getBalance(investor) |
|
||||||
|
|
||||||
post.minus(pre).should.be.bignumber.equal(lessThanGoal) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should forward funds to wallet after end if goal was reached', async function () { |
|
||||||
await increaseTimeTo(this.startTime) |
|
||||||
await this.crowdsale.sendTransaction({value: goal, from: investor}) |
|
||||||
await increaseTimeTo(this.afterEndTime) |
|
||||||
|
|
||||||
const pre = web3.eth.getBalance(wallet) |
|
||||||
await this.crowdsale.finalize({from: owner}) |
|
||||||
const post = web3.eth.getBalance(wallet) |
|
||||||
|
|
||||||
post.minus(pre).should.be.bignumber.equal(goal) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
@ -0,0 +1,80 @@ |
|||||||
|
import ether from './helpers/ether'; |
||||||
|
import { advanceBlock } from './helpers/advanceToBlock'; |
||||||
|
import { increaseTimeTo, duration } from './helpers/increaseTime'; |
||||||
|
import latestTime from './helpers/latestTime'; |
||||||
|
import EVMRevert from './helpers/EVMRevert'; |
||||||
|
|
||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const RefundableCrowdsale = artifacts.require('./mocks/RefundableCrowdsaleImpl.sol'); |
||||||
|
|
||||||
|
contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) { |
||||||
|
const rate = new BigNumber(1000); |
||||||
|
const goal = ether(800); |
||||||
|
const lessThanGoal = ether(750); |
||||||
|
|
||||||
|
before(async function () { |
||||||
|
// Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
|
||||||
|
await advanceBlock(); |
||||||
|
}); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
this.startTime = latestTime() + duration.weeks(1); |
||||||
|
this.endTime = this.startTime + duration.weeks(1); |
||||||
|
this.afterEndTime = this.endTime + duration.seconds(1); |
||||||
|
|
||||||
|
this.crowdsale = await RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, goal, { from: owner }); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('creating a valid crowdsale', function () { |
||||||
|
it('should fail with zero goal', async function () { |
||||||
|
await RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, { from: owner }) |
||||||
|
.should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should deny refunds before end', async function () { |
||||||
|
await this.crowdsale.claimRefund({ from: investor }).should.be.rejectedWith(EVMRevert); |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
await this.crowdsale.claimRefund({ from: investor }).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should deny refunds after end if goal was reached', async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
await this.crowdsale.sendTransaction({ value: goal, from: investor }); |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
await this.crowdsale.claimRefund({ from: investor }).should.be.rejectedWith(EVMRevert); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should allow refunds after end if goal was not reached', async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
await this.crowdsale.sendTransaction({ value: lessThanGoal, from: investor }); |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
|
||||||
|
await this.crowdsale.finalize({ from: owner }); |
||||||
|
|
||||||
|
const pre = web3.eth.getBalance(investor); |
||||||
|
await this.crowdsale.claimRefund({ from: investor, gasPrice: 0 }) |
||||||
|
.should.be.fulfilled; |
||||||
|
const post = web3.eth.getBalance(investor); |
||||||
|
|
||||||
|
post.minus(pre).should.be.bignumber.equal(lessThanGoal); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should forward funds to wallet after end if goal was reached', async function () { |
||||||
|
await increaseTimeTo(this.startTime); |
||||||
|
await this.crowdsale.sendTransaction({ value: goal, from: investor }); |
||||||
|
await increaseTimeTo(this.afterEndTime); |
||||||
|
|
||||||
|
const pre = web3.eth.getBalance(wallet); |
||||||
|
await this.crowdsale.finalize({ from: owner }); |
||||||
|
const post = web3.eth.getBalance(wallet); |
||||||
|
|
||||||
|
post.minus(pre).should.be.bignumber.equal(goal); |
||||||
|
}); |
||||||
|
}); |
@ -1,72 +1,70 @@ |
|||||||
const assertRevert = require('./helpers/assertRevert'); |
const assertRevert = require('./helpers/assertRevert'); |
||||||
const assertJump = require('./helpers/assertJump'); |
const assertJump = require('./helpers/assertJump'); |
||||||
var SafeMathMock = artifacts.require("./helpers/SafeMathMock.sol"); |
var SafeMathMock = artifacts.require('./mocks/SafeMathMock.sol'); |
||||||
|
|
||||||
contract('SafeMath', function (accounts) { |
contract('SafeMath', function (accounts) { |
||||||
|
|
||||||
let safeMath; |
let safeMath; |
||||||
|
|
||||||
before(async function () { |
before(async function () { |
||||||
safeMath = await SafeMathMock.new(); |
safeMath = await SafeMathMock.new(); |
||||||
}); |
}); |
||||||
|
|
||||||
it("multiplies correctly", async function() { |
it('multiplies correctly', async function () { |
||||||
let a = 5678; |
let a = 5678; |
||||||
let b = 1234; |
let b = 1234; |
||||||
let mult = await safeMath.multiply(a, b); |
await safeMath.multiply(a, b); |
||||||
let result = await safeMath.result(); |
let result = await safeMath.result(); |
||||||
assert.equal(result, a * b); |
assert.equal(result, a * b); |
||||||
}); |
}); |
||||||
|
|
||||||
it("adds correctly", async function() { |
it('adds correctly', async function () { |
||||||
let a = 5678; |
let a = 5678; |
||||||
let b = 1234; |
let b = 1234; |
||||||
let add = await safeMath.add(a, b); |
await safeMath.add(a, b); |
||||||
let result = await safeMath.result(); |
let result = await safeMath.result(); |
||||||
|
|
||||||
assert.equal(result, a + b); |
assert.equal(result, a + b); |
||||||
}); |
}); |
||||||
|
|
||||||
it("subtracts correctly", async function() { |
it('subtracts correctly', async function () { |
||||||
let a = 5678; |
let a = 5678; |
||||||
let b = 1234; |
let b = 1234; |
||||||
let subtract = await safeMath.subtract(a, b); |
await safeMath.subtract(a, b); |
||||||
let result = await safeMath.result(); |
let result = await safeMath.result(); |
||||||
|
|
||||||
assert.equal(result, a - b); |
assert.equal(result, a - b); |
||||||
}); |
}); |
||||||
|
|
||||||
it("should throw an error if subtraction result would be negative", async function () { |
it('should throw an error if subtraction result would be negative', async function () { |
||||||
let a = 1234; |
let a = 1234; |
||||||
let b = 5678; |
let b = 5678; |
||||||
try { |
try { |
||||||
let subtract = await safeMath.subtract(a, b); |
await safeMath.subtract(a, b); |
||||||
assert.fail('should have thrown before'); |
assert.fail('should have thrown before'); |
||||||
} catch (error) { |
} catch (error) { |
||||||
assertJump(error); |
assertJump(error); |
||||||
} |
} |
||||||
}); |
}); |
||||||
|
|
||||||
it("should throw an error on addition overflow", async function() { |
it('should throw an error on addition overflow', async function () { |
||||||
let a = 115792089237316195423570985008687907853269984665640564039457584007913129639935; |
let a = 115792089237316195423570985008687907853269984665640564039457584007913129639935; |
||||||
let b = 1; |
let b = 1; |
||||||
try { |
try { |
||||||
let add = await safeMath.add(a, b); |
await safeMath.add(a, b); |
||||||
assert.fail('should have thrown before'); |
assert.fail('should have thrown before'); |
||||||
} catch (error) { |
} catch (error) { |
||||||
assertRevert(error); |
assertRevert(error); |
||||||
} |
} |
||||||
}); |
}); |
||||||
|
|
||||||
it("should throw an error on multiplication overflow", async function() { |
it('should throw an error on multiplication overflow', async function () { |
||||||
let a = 115792089237316195423570985008687907853269984665640564039457584007913129639933; |
let a = 115792089237316195423570985008687907853269984665640564039457584007913129639933; |
||||||
let b = 2; |
let b = 2; |
||||||
try { |
try { |
||||||
let multiply = await safeMath.multiply(a, b); |
await safeMath.multiply(a, b); |
||||||
assert.fail('should have thrown before'); |
assert.fail('should have thrown before'); |
||||||
} catch (error) { |
} catch (error) { |
||||||
assertRevert(error); |
assertRevert(error); |
||||||
} |
} |
||||||
}); |
}); |
||||||
|
|
||||||
}); |
}); |
@ -1,78 +0,0 @@ |
|||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
const should = require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
const EVMThrow = require('./helpers/EVMThrow.js') |
|
||||||
const SplitPayment = artifacts.require('../contracts/payment/SplitPayment.sol') |
|
||||||
|
|
||||||
contract('SplitPayment', function ([owner, payee1, payee2, payee3, nonpayee1, payer1]) { |
|
||||||
const amount = web3.toWei(1.0, 'ether') |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
this.payees = [payee1, payee2, payee3] |
|
||||||
this.shares = [20, 10, 70] |
|
||||||
|
|
||||||
this.contract = await SplitPayment.new(this.payees, this.shares) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should accept payments', async function () { |
|
||||||
await web3.eth.sendTransaction({ from: owner, to: this.contract.address, value: amount }) |
|
||||||
|
|
||||||
const balance = web3.eth.getBalance(this.contract.address) |
|
||||||
balance.should.be.bignumber.equal(amount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should store shares if address is payee', async function () { |
|
||||||
const shares = await this.contract.shares.call(payee1) |
|
||||||
shares.should.be.bignumber.not.equal(0) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should not store shares if address is not payee', async function () { |
|
||||||
const shares = await this.contract.shares.call(nonpayee1) |
|
||||||
shares.should.be.bignumber.equal(0) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should throw if no funds to claim', async function () { |
|
||||||
await this.contract.claim({from: payee1}).should.be.rejectedWith(EVMThrow) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should throw if non-payee want to claim', async function () { |
|
||||||
await web3.eth.sendTransaction({from: payer1, to: this.contract.address, value: amount}) |
|
||||||
await this.contract.claim({from: nonpayee1}).should.be.rejectedWith(EVMThrow) |
|
||||||
}) |
|
||||||
|
|
||||||
it('should distribute funds to payees', async function () { |
|
||||||
await web3.eth.sendTransaction({from: payer1, to: this.contract.address, value: amount}) |
|
||||||
|
|
||||||
// receive funds
|
|
||||||
const initBalance = web3.eth.getBalance(this.contract.address) |
|
||||||
initBalance.should.be.bignumber.equal(amount) |
|
||||||
|
|
||||||
// distribute to payees
|
|
||||||
const initAmount1 = web3.eth.getBalance(payee1) |
|
||||||
await this.contract.claim({from: payee1}) |
|
||||||
const profit1 = web3.eth.getBalance(payee1) - initAmount1 |
|
||||||
assert(Math.abs(profit1 - web3.toWei(0.20, 'ether')) < 1e16) |
|
||||||
|
|
||||||
const initAmount2 = web3.eth.getBalance(payee2) |
|
||||||
await this.contract.claim({from: payee2}) |
|
||||||
const profit2 = web3.eth.getBalance(payee2) - initAmount2 |
|
||||||
assert(Math.abs(profit2 - web3.toWei(0.10, 'ether')) < 1e16) |
|
||||||
|
|
||||||
const initAmount3 = web3.eth.getBalance(payee3) |
|
||||||
await this.contract.claim({from: payee3}) |
|
||||||
const profit3 = web3.eth.getBalance(payee3) - initAmount3 |
|
||||||
assert(Math.abs(profit3 - web3.toWei(0.70, 'ether')) < 1e16) |
|
||||||
|
|
||||||
// end balance should be zero
|
|
||||||
const endBalance = web3.eth.getBalance(this.contract.address) |
|
||||||
endBalance.should.be.bignumber.equal(0) |
|
||||||
|
|
||||||
// check correct funds released accounting
|
|
||||||
const totalReleased = await this.contract.totalReleased.call() |
|
||||||
totalReleased.should.be.bignumber.equal(initBalance) |
|
||||||
}) |
|
||||||
}) |
|
@ -0,0 +1,78 @@ |
|||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const EVMThrow = require('./helpers/EVMThrow.js'); |
||||||
|
const SplitPayment = artifacts.require('../contracts/payment/SplitPayment.sol'); |
||||||
|
|
||||||
|
contract('SplitPayment', function ([owner, payee1, payee2, payee3, nonpayee1, payer1]) { |
||||||
|
const amount = web3.toWei(1.0, 'ether'); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
this.payees = [payee1, payee2, payee3]; |
||||||
|
this.shares = [20, 10, 70]; |
||||||
|
|
||||||
|
this.contract = await SplitPayment.new(this.payees, this.shares); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should accept payments', async function () { |
||||||
|
await web3.eth.sendTransaction({ from: owner, to: this.contract.address, value: amount }); |
||||||
|
|
||||||
|
const balance = web3.eth.getBalance(this.contract.address); |
||||||
|
balance.should.be.bignumber.equal(amount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should store shares if address is payee', async function () { |
||||||
|
const shares = await this.contract.shares.call(payee1); |
||||||
|
shares.should.be.bignumber.not.equal(0); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should not store shares if address is not payee', async function () { |
||||||
|
const shares = await this.contract.shares.call(nonpayee1); |
||||||
|
shares.should.be.bignumber.equal(0); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should throw if no funds to claim', async function () { |
||||||
|
await this.contract.claim({ from: payee1 }).should.be.rejectedWith(EVMThrow); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should throw if non-payee want to claim', async function () { |
||||||
|
await web3.eth.sendTransaction({ from: payer1, to: this.contract.address, value: amount }); |
||||||
|
await this.contract.claim({ from: nonpayee1 }).should.be.rejectedWith(EVMThrow); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should distribute funds to payees', async function () { |
||||||
|
await web3.eth.sendTransaction({ from: payer1, to: this.contract.address, value: amount }); |
||||||
|
|
||||||
|
// receive funds
|
||||||
|
const initBalance = web3.eth.getBalance(this.contract.address); |
||||||
|
initBalance.should.be.bignumber.equal(amount); |
||||||
|
|
||||||
|
// distribute to payees
|
||||||
|
const initAmount1 = web3.eth.getBalance(payee1); |
||||||
|
await this.contract.claim({ from: payee1 }); |
||||||
|
const profit1 = web3.eth.getBalance(payee1) - initAmount1; |
||||||
|
assert(Math.abs(profit1 - web3.toWei(0.20, 'ether')) < 1e16); |
||||||
|
|
||||||
|
const initAmount2 = web3.eth.getBalance(payee2); |
||||||
|
await this.contract.claim({ from: payee2 }); |
||||||
|
const profit2 = web3.eth.getBalance(payee2) - initAmount2; |
||||||
|
assert(Math.abs(profit2 - web3.toWei(0.10, 'ether')) < 1e16); |
||||||
|
|
||||||
|
const initAmount3 = web3.eth.getBalance(payee3); |
||||||
|
await this.contract.claim({ from: payee3 }); |
||||||
|
const profit3 = web3.eth.getBalance(payee3) - initAmount3; |
||||||
|
assert(Math.abs(profit3 - web3.toWei(0.70, 'ether')) < 1e16); |
||||||
|
|
||||||
|
// end balance should be zero
|
||||||
|
const endBalance = web3.eth.getBalance(this.contract.address); |
||||||
|
endBalance.should.be.bignumber.equal(0); |
||||||
|
|
||||||
|
// check correct funds released accounting
|
||||||
|
const totalReleased = await this.contract.totalReleased.call(); |
||||||
|
totalReleased.should.be.bignumber.equal(initBalance); |
||||||
|
}); |
||||||
|
}); |
@ -1,7 +1,6 @@ |
|||||||
'use strict'; |
|
||||||
|
|
||||||
var TokenDestructible = artifacts.require('../contracts/lifecycle/TokenDestructible.sol'); |
var TokenDestructible = artifacts.require('../contracts/lifecycle/TokenDestructible.sol'); |
||||||
var StandardTokenMock = artifacts.require("./helpers/StandardTokenMock.sol"); |
var StandardTokenMock = artifacts.require('./mocks/StandardTokenMock.sol'); |
||||||
require('./helpers/transactionMined.js'); |
require('./helpers/transactionMined.js'); |
||||||
|
|
||||||
contract('TokenDestructible', function (accounts) { |
contract('TokenDestructible', function (accounts) { |
@ -1,57 +0,0 @@ |
|||||||
const BigNumber = web3.BigNumber |
|
||||||
|
|
||||||
require('chai') |
|
||||||
.use(require('chai-as-promised')) |
|
||||||
.use(require('chai-bignumber')(BigNumber)) |
|
||||||
.should() |
|
||||||
|
|
||||||
|
|
||||||
import latestTime from './helpers/latestTime' |
|
||||||
import {increaseTimeTo, duration} from './helpers/increaseTime' |
|
||||||
|
|
||||||
const MintableToken = artifacts.require('MintableToken') |
|
||||||
const TokenTimelock = artifacts.require('TokenTimelock') |
|
||||||
|
|
||||||
contract('TokenTimelock', function ([_, owner, beneficiary]) { |
|
||||||
|
|
||||||
const amount = new BigNumber(100) |
|
||||||
|
|
||||||
beforeEach(async function () { |
|
||||||
this.token = await MintableToken.new({from: owner}) |
|
||||||
this.releaseTime = latestTime() + duration.years(1) |
|
||||||
this.timelock = await TokenTimelock.new(this.token.address, beneficiary, this.releaseTime) |
|
||||||
await this.token.mint(this.timelock.address, amount, {from: owner}) |
|
||||||
}) |
|
||||||
|
|
||||||
it('cannot be released before time limit', async function () { |
|
||||||
await this.timelock.release().should.be.rejected |
|
||||||
}) |
|
||||||
|
|
||||||
it('cannot be released just before time limit', async function () { |
|
||||||
await increaseTimeTo(this.releaseTime - duration.seconds(3)) |
|
||||||
await this.timelock.release().should.be.rejected |
|
||||||
}) |
|
||||||
|
|
||||||
it('can be released just after limit', async function () { |
|
||||||
await increaseTimeTo(this.releaseTime + duration.seconds(1)) |
|
||||||
await this.timelock.release().should.be.fulfilled |
|
||||||
const balance = await this.token.balanceOf(beneficiary) |
|
||||||
balance.should.be.bignumber.equal(amount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('can be released after time limit', async function () { |
|
||||||
await increaseTimeTo(this.releaseTime + duration.years(1)) |
|
||||||
await this.timelock.release().should.be.fulfilled |
|
||||||
const balance = await this.token.balanceOf(beneficiary) |
|
||||||
balance.should.be.bignumber.equal(amount) |
|
||||||
}) |
|
||||||
|
|
||||||
it('cannot be released twice', async function () { |
|
||||||
await increaseTimeTo(this.releaseTime + duration.years(1)) |
|
||||||
await this.timelock.release().should.be.fulfilled |
|
||||||
await this.timelock.release().should.be.rejected |
|
||||||
const balance = await this.token.balanceOf(beneficiary) |
|
||||||
balance.should.be.bignumber.equal(amount) |
|
||||||
}) |
|
||||||
|
|
||||||
}) |
|
@ -0,0 +1,54 @@ |
|||||||
|
import latestTime from './helpers/latestTime'; |
||||||
|
import { increaseTimeTo, duration } from './helpers/increaseTime'; |
||||||
|
|
||||||
|
const BigNumber = web3.BigNumber; |
||||||
|
|
||||||
|
require('chai') |
||||||
|
.use(require('chai-as-promised')) |
||||||
|
.use(require('chai-bignumber')(BigNumber)) |
||||||
|
.should(); |
||||||
|
|
||||||
|
const MintableToken = artifacts.require('MintableToken'); |
||||||
|
const TokenTimelock = artifacts.require('TokenTimelock'); |
||||||
|
|
||||||
|
contract('TokenTimelock', function ([_, owner, beneficiary]) { |
||||||
|
const amount = new BigNumber(100); |
||||||
|
|
||||||
|
beforeEach(async function () { |
||||||
|
this.token = await MintableToken.new({ from: owner }); |
||||||
|
this.releaseTime = latestTime() + duration.years(1); |
||||||
|
this.timelock = await TokenTimelock.new(this.token.address, beneficiary, this.releaseTime); |
||||||
|
await this.token.mint(this.timelock.address, amount, { from: owner }); |
||||||
|
}); |
||||||
|
|
||||||
|
it('cannot be released before time limit', async function () { |
||||||
|
await this.timelock.release().should.be.rejected; |
||||||
|
}); |
||||||
|
|
||||||
|
it('cannot be released just before time limit', async function () { |
||||||
|
await increaseTimeTo(this.releaseTime - duration.seconds(3)); |
||||||
|
await this.timelock.release().should.be.rejected; |
||||||
|
}); |
||||||
|
|
||||||
|
it('can be released just after limit', async function () { |
||||||
|
await increaseTimeTo(this.releaseTime + duration.seconds(1)); |
||||||
|
await this.timelock.release().should.be.fulfilled; |
||||||
|
const balance = await this.token.balanceOf(beneficiary); |
||||||
|
balance.should.be.bignumber.equal(amount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('can be released after time limit', async function () { |
||||||
|
await increaseTimeTo(this.releaseTime + duration.years(1)); |
||||||
|
await this.timelock.release().should.be.fulfilled; |
||||||
|
const balance = await this.token.balanceOf(beneficiary); |
||||||
|
balance.should.be.bignumber.equal(amount); |
||||||
|
}); |
||||||
|
|
||||||
|
it('cannot be released twice', async function () { |
||||||
|
await increaseTimeTo(this.releaseTime + duration.years(1)); |
||||||
|
await this.timelock.release().should.be.fulfilled; |
||||||
|
await this.timelock.release().should.be.rejected; |
||||||
|
const balance = await this.token.balanceOf(beneficiary); |
||||||
|
balance.should.be.bignumber.equal(amount); |
||||||
|
}); |
||||||
|
}); |
@ -1 +1 @@ |
|||||||
export default 'revert' |
export default 'revert'; |
||||||
|
@ -1 +1 @@ |
|||||||
export default 'invalid opcode' |
export default 'invalid opcode'; |
||||||
|
@ -1,3 +1,3 @@ |
|||||||
module.exports = function (error) { |
module.exports = function (error) { |
||||||
assert.isAbove(error.message.search('invalid opcode'), -1, 'Invalid opcode error must be returned'); |
assert.isAbove(error.message.search('invalid opcode'), -1, 'Invalid opcode error must be returned'); |
||||||
} |
}; |
||||||
|
@ -1,3 +1,3 @@ |
|||||||
module.exports = function (error) { |
module.exports = function (error) { |
||||||
assert.isAbove(error.message.search('revert'), -1, 'Error containing "revert" must be returned'); |
assert.isAbove(error.message.search('revert'), -1, 'Error containing "revert" must be returned'); |
||||||
} |
}; |
||||||
|
@ -1,3 +1,3 @@ |
|||||||
export default function ether (n) { |
export default function ether (n) { |
||||||
return new web3.BigNumber(web3.toWei(n, 'ether')) |
return new web3.BigNumber(web3.toWei(n, 'ether')); |
||||||
} |
} |
||||||
|
@ -1,4 +1,4 @@ |
|||||||
export default func => |
export default func => |
||||||
(...args) => |
(...args) => |
||||||
new Promise((accept, reject) => |
new Promise((resolve, reject) => |
||||||
func(...args, (error, data) => error ? reject(error) : accept(data))); |
func(...args, (error, data) => error ? reject(error) : resolve(data))); |
||||||
|
@ -1,32 +1,48 @@ |
|||||||
|
require('dotenv').config(); |
||||||
require('babel-register'); |
require('babel-register'); |
||||||
require('babel-polyfill'); |
require('babel-polyfill'); |
||||||
|
|
||||||
var provider; |
const HDWalletProvider = require('truffle-hdwallet-provider'); |
||||||
var HDWalletProvider = require('truffle-hdwallet-provider'); |
|
||||||
var mnemonic = '[REDACTED]'; |
|
||||||
|
|
||||||
if (!process.env.SOLIDITY_COVERAGE){ |
const providerWithMnemonic = (mnemonic, rpcEndpoint) => |
||||||
provider = new HDWalletProvider(mnemonic, 'https://ropsten.infura.io/') |
new HDWalletProvider(mnemonic, rpcEndpoint); |
||||||
} |
|
||||||
|
|
||||||
|
const infuraProvider = network => providerWithMnemonic( |
||||||
|
process.env.MNEMONIC || '', |
||||||
|
`https://${network}.infura.io/${process.env.INFURA_API_KEY}` |
||||||
|
); |
||||||
|
|
||||||
|
const ropstenProvider = process.env.SOLIDITY_COVERAGE |
||||||
|
? undefined |
||||||
|
: infuraProvider('ropsten'); |
||||||
|
|
||||||
module.exports = { |
module.exports = { |
||||||
networks: { |
networks: { |
||||||
development: { |
development: { |
||||||
host: 'localhost', |
host: 'localhost', |
||||||
port: 8545, |
port: 8545, |
||||||
network_id: '*' |
network_id: '*', // eslint-disable-line camelcase
|
||||||
}, |
}, |
||||||
ropsten: { |
ropsten: { |
||||||
provider: provider, |
provider: ropstenProvider, |
||||||
network_id: 3 // official id of the ropsten network
|
network_id: 3, // eslint-disable-line camelcase
|
||||||
}, |
}, |
||||||
coverage: { |
coverage: { |
||||||
host: "localhost", |
host: 'localhost', |
||||||
network_id: "*", |
network_id: '*', // eslint-disable-line camelcase
|
||||||
port: 8555, |
port: 8555, |
||||||
gas: 0xfffffffffff, |
gas: 0xfffffffffff, |
||||||
gasPrice: 0x01 |
gasPrice: 0x01, |
||||||
} |
}, |
||||||
} |
testrpc: { |
||||||
|
host: 'localhost', |
||||||
|
port: 8545, |
||||||
|
network_id: '*', // eslint-disable-line camelcase
|
||||||
|
}, |
||||||
|
ganache: { |
||||||
|
host: 'localhost', |
||||||
|
port: 7545, |
||||||
|
network_id: '*', // eslint-disable-line camelcase
|
||||||
|
}, |
||||||
|
}, |
||||||
}; |
}; |
||||||
|
Loading…
Reference in new issue