Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
O
openzeppelin-contracts-upgradeable
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
俞永鹏
openzeppelin-contracts-upgradeable
Commits
2b079136
Commit
2b079136
authored
Aug 10, 2017
by
Francisco Giordano
Committed by
GitHub
Aug 10, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #353 from jakub-wojciechowski/master
Change crowdsales to use timestamps instead of block numbers #350
parents
69daed77
46c5759b
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
153 additions
and
89 deletions
+153
-89
Crowdsale.sol
contracts/crowdsale/Crowdsale.sol
+11
-12
SampleCrowdsale.sol
contracts/examples/SampleCrowdsale.sol
+2
-2
CappedCrowdsale.js
test/CappedCrowdsale.js
+19
-13
Crowdsale.js
test/Crowdsale.js
+18
-9
FinalizableCrowdsale.js
test/FinalizableCrowdsale.js
+18
-9
RefundableCrowdsale.js
test/RefundableCrowdsale.js
+24
-17
SampleCrowdsale.js
test/SampleCrowdsale.js
+21
-12
TokenTimelock.js
test/TokenTimelock.js
+4
-4
CappedCrowdsaleImpl.sol
test/helpers/CappedCrowdsaleImpl.sol
+3
-3
FinalizableCrowdsaleImpl.sol
test/helpers/FinalizableCrowdsaleImpl.sol
+3
-3
RefundableCrowdsaleImpl.sol
test/helpers/RefundableCrowdsaleImpl.sol
+3
-3
increaseTime.js
test/helpers/increaseTime.js
+27
-2
No files found.
contracts/crowdsale/Crowdsale.sol
View file @
2b079136
...
@@ -6,7 +6,7 @@ import '../math/SafeMath.sol';
...
@@ -6,7 +6,7 @@ import '../math/SafeMath.sol';
/**
/**
* @title Crowdsale
* @title Crowdsale
* @dev Crowdsale is a base contract for managing a token crowdsale.
* @dev Crowdsale is a base contract for managing a token crowdsale.
* Crowdsales have a start and end
block
, where investors can make
* Crowdsales have a start and end
timestamps
, where investors can make
* token purchases and the crowdsale will assign them tokens based
* token purchases and the crowdsale will assign them tokens based
* on a token per ETH rate. Funds collected are forwarded to a wallet
* on a token per ETH rate. Funds collected are forwarded to a wallet
* as they arrive.
* as they arrive.
...
@@ -17,9 +17,9 @@ contract Crowdsale {
...
@@ -17,9 +17,9 @@ contract Crowdsale {
// The token being sold
// The token being sold
MintableToken public token;
MintableToken public token;
// start and end
block
where investments are allowed (both inclusive)
// start and end
timestamps
where investments are allowed (both inclusive)
uint256 public start
Block
;
uint256 public start
Time
;
uint256 public end
Block
;
uint256 public end
Time
;
// address where funds are collected
// address where funds are collected
address public wallet;
address public wallet;
...
@@ -40,15 +40,15 @@ contract Crowdsale {
...
@@ -40,15 +40,15 @@ contract Crowdsale {
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
function Crowdsale(uint256 _start
Block, uint256 _endBlock
, uint256 _rate, address _wallet) {
function Crowdsale(uint256 _start
Time, uint256 _endTime
, uint256 _rate, address _wallet) {
require(_start
Block >= block.number
);
require(_start
Time >= now
);
require(_end
Block >= _startBlock
);
require(_end
Time >= _startTime
);
require(_rate > 0);
require(_rate > 0);
require(_wallet != 0x0);
require(_wallet != 0x0);
token = createTokenContract();
token = createTokenContract();
start
Block = _startBlock
;
start
Time = _startTime
;
end
Block = _endBlock
;
end
Time = _endTime
;
rate = _rate;
rate = _rate;
wallet = _wallet;
wallet = _wallet;
}
}
...
@@ -92,15 +92,14 @@ contract Crowdsale {
...
@@ -92,15 +92,14 @@ contract Crowdsale {
// @return true if the transaction can buy tokens
// @return true if the transaction can buy tokens
function validPurchase() internal constant returns (bool) {
function validPurchase() internal constant returns (bool) {
uint256 current = block.number;
bool withinPeriod = now >= startTime && now <= endTime;
bool withinPeriod = current >= startBlock && current <= endBlock;
bool nonZeroPurchase = msg.value != 0;
bool nonZeroPurchase = msg.value != 0;
return withinPeriod && nonZeroPurchase;
return withinPeriod && nonZeroPurchase;
}
}
// @return true if crowdsale event has ended
// @return true if crowdsale event has ended
function hasEnded() public constant returns (bool) {
function hasEnded() public constant returns (bool) {
return
block.number > endBlock
;
return
now > endTime
;
}
}
...
...
contracts/examples/SampleCrowdsale.sol
View file @
2b079136
...
@@ -30,11 +30,11 @@ contract SampleCrowdsaleToken is MintableToken {
...
@@ -30,11 +30,11 @@ contract SampleCrowdsaleToken is MintableToken {
*/
*/
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale {
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale {
function SampleCrowdsale(uint256 _start
Block, uint256 _endBlock
, uint256 _rate, uint256 _goal, uint256 _cap, address _wallet)
function SampleCrowdsale(uint256 _start
Time, uint256 _endTime
, uint256 _rate, uint256 _goal, uint256 _cap, address _wallet)
CappedCrowdsale(_cap)
CappedCrowdsale(_cap)
FinalizableCrowdsale()
FinalizableCrowdsale()
RefundableCrowdsale(_goal)
RefundableCrowdsale(_goal)
Crowdsale(_start
Block, _endBlock
, _rate, _wallet)
Crowdsale(_start
Time, _endTime
, _rate, _wallet)
{
{
//As goal needs to be met for a successful crowdsale
//As goal needs to be met for a successful crowdsale
//the value needs to less or equal than a cap which is limit for accepted funds
//the value needs to less or equal than a cap which is limit for accepted funds
...
...
test/CappedCrowdsale.js
View file @
2b079136
import
ether
from
'./helpers/ether'
import
ether
from
'./helpers/ether'
import
advanceToBlock
from
'./helpers/advanceToBlock'
import
{
advanceBlock
}
from
'./helpers/advanceToBlock'
import
{
increaseTimeTo
,
duration
}
from
'./helpers/increaseTime'
import
latestTime
from
'./helpers/latestTime'
import
EVMThrow
from
'./helpers/EVMThrow'
import
EVMThrow
from
'./helpers/EVMThrow'
const
BigNumber
=
web3
.
BigNumber
const
BigNumber
=
web3
.
BigNumber
...
@@ -19,28 +21,32 @@ contract('CappedCrowdsale', function ([_, wallet]) {
...
@@ -19,28 +21,32 @@ contract('CappedCrowdsale', function ([_, wallet]) {
const
cap
=
ether
(
300
)
const
cap
=
ether
(
300
)
const
lessThanCap
=
ether
(
60
)
const
lessThanCap
=
ether
(
60
)
describe
(
'creating a valid crowdsale'
,
function
()
{
before
(
async
function
()
{
//Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
it
(
'should fail with zero cap'
,
async
function
()
{
await
advanceBlock
()
await
CappedCrowdsale
.
new
(
this
.
startBlock
,
this
.
endBlock
,
rate
,
wallet
,
0
).
should
.
be
.
rejectedWith
(
EVMThrow
);
})
})
});
beforeEach
(
async
function
()
{
beforeEach
(
async
function
()
{
this
.
start
Block
=
web3
.
eth
.
blockNumber
+
10
this
.
start
Time
=
latestTime
().
unix
()
+
duration
.
weeks
(
1
);
this
.
end
Block
=
web3
.
eth
.
blockNumber
+
20
this
.
end
Time
=
this
.
startTime
+
duration
.
weeks
(
1
);
this
.
crowdsale
=
await
CappedCrowdsale
.
new
(
this
.
start
Block
,
this
.
endBlock
,
rate
,
wallet
,
cap
)
this
.
crowdsale
=
await
CappedCrowdsale
.
new
(
this
.
start
Time
,
this
.
endTime
,
rate
,
wallet
,
cap
)
this
.
token
=
MintableToken
.
at
(
await
this
.
crowdsale
.
token
())
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
(
EVMThrow
);
})
});
describe
(
'accepting payments'
,
function
()
{
describe
(
'accepting payments'
,
function
()
{
beforeEach
(
async
function
()
{
beforeEach
(
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
-
1
)
await
increaseTimeTo
(
this
.
startTime
)
})
})
it
(
'should accept payments within cap'
,
async
function
()
{
it
(
'should accept payments within cap'
,
async
function
()
{
...
@@ -62,7 +68,7 @@ contract('CappedCrowdsale', function ([_, wallet]) {
...
@@ -62,7 +68,7 @@ contract('CappedCrowdsale', function ([_, wallet]) {
describe
(
'ending'
,
function
()
{
describe
(
'ending'
,
function
()
{
beforeEach
(
async
function
()
{
beforeEach
(
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
-
1
)
await
increaseTimeTo
(
this
.
startTime
)
})
})
it
(
'should not be ended if under cap'
,
async
function
()
{
it
(
'should not be ended if under cap'
,
async
function
()
{
...
...
test/Crowdsale.js
View file @
2b079136
import
ether
from
'./helpers/ether'
import
ether
from
'./helpers/ether'
import
advanceToBlock
from
'./helpers/advanceToBlock'
import
{
advanceBlock
}
from
'./helpers/advanceToBlock'
import
{
increaseTimeTo
,
duration
}
from
'./helpers/increaseTime'
import
latestTime
from
'./helpers/latestTime'
import
EVMThrow
from
'./helpers/EVMThrow'
import
EVMThrow
from
'./helpers/EVMThrow'
const
BigNumber
=
web3
.
BigNumber
const
BigNumber
=
web3
.
BigNumber
...
@@ -19,11 +21,18 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
...
@@ -19,11 +21,18 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
const
expectedTokenAmount
=
rate
.
mul
(
value
)
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
()
{
beforeEach
(
async
function
()
{
this
.
startBlock
=
web3
.
eth
.
blockNumber
+
10
this
.
startTime
=
latestTime
().
unix
()
+
duration
.
weeks
(
1
);
this
.
endBlock
=
web3
.
eth
.
blockNumber
+
20
this
.
endTime
=
this
.
startTime
+
duration
.
weeks
(
1
);
this
.
afterEndTime
=
this
.
endTime
+
duration
.
seconds
(
1
)
this
.
crowdsale
=
await
Crowdsale
.
new
(
this
.
start
Block
,
this
.
endBlock
,
rate
,
wallet
)
this
.
crowdsale
=
await
Crowdsale
.
new
(
this
.
start
Time
,
this
.
endTime
,
rate
,
wallet
)
this
.
token
=
MintableToken
.
at
(
await
this
.
crowdsale
.
token
())
this
.
token
=
MintableToken
.
at
(
await
this
.
crowdsale
.
token
())
})
})
...
@@ -36,7 +45,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
...
@@ -36,7 +45,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
it
(
'should be ended only after end'
,
async
function
()
{
it
(
'should be ended only after end'
,
async
function
()
{
let
ended
=
await
this
.
crowdsale
.
hasEnded
()
let
ended
=
await
this
.
crowdsale
.
hasEnded
()
ended
.
should
.
equal
(
false
)
ended
.
should
.
equal
(
false
)
await
advanceToBlock
(
this
.
endBlock
+
1
)
await
increaseTimeTo
(
this
.
afterEndTime
)
ended
=
await
this
.
crowdsale
.
hasEnded
()
ended
=
await
this
.
crowdsale
.
hasEnded
()
ended
.
should
.
equal
(
true
)
ended
.
should
.
equal
(
true
)
})
})
...
@@ -49,13 +58,13 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
...
@@ -49,13 +58,13 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
})
})
it
(
'should accept payments after start'
,
async
function
()
{
it
(
'should accept payments after start'
,
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
-
1
)
await
increaseTimeTo
(
this
.
startTime
)
await
this
.
crowdsale
.
send
(
value
).
should
.
be
.
fulfilled
await
this
.
crowdsale
.
send
(
value
).
should
.
be
.
fulfilled
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
value
,
from
:
purchaser
}).
should
.
be
.
fulfilled
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
value
,
from
:
purchaser
}).
should
.
be
.
fulfilled
})
})
it
(
'should reject payments after end'
,
async
function
()
{
it
(
'should reject payments after end'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
await
this
.
crowdsale
.
send
(
value
).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
send
(
value
).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
value
,
from
:
purchaser
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
value
,
from
:
purchaser
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
})
})
...
@@ -65,7 +74,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
...
@@ -65,7 +74,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
describe
(
'high-level purchase'
,
function
()
{
describe
(
'high-level purchase'
,
function
()
{
beforeEach
(
async
function
()
{
beforeEach
(
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
)
await
increaseTimeTo
(
this
.
startTime
)
})
})
it
(
'should log purchase'
,
async
function
()
{
it
(
'should log purchase'
,
async
function
()
{
...
@@ -104,7 +113,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
...
@@ -104,7 +113,7 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
describe
(
'low-level purchase'
,
function
()
{
describe
(
'low-level purchase'
,
function
()
{
beforeEach
(
async
function
()
{
beforeEach
(
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
)
await
increaseTimeTo
(
this
.
startTime
)
})
})
it
(
'should log purchase'
,
async
function
()
{
it
(
'should log purchase'
,
async
function
()
{
...
...
test/FinalizableCrowdsale.js
View file @
2b079136
import
advanceToBlock
from
'./helpers/advanceToBlock'
import
{
advanceBlock
}
from
'./helpers/advanceToBlock'
import
{
increaseTimeTo
,
duration
}
from
'./helpers/increaseTime'
import
latestTime
from
'./helpers/latestTime'
import
EVMThrow
from
'./helpers/EVMThrow'
import
EVMThrow
from
'./helpers/EVMThrow'
const
BigNumber
=
web3
.
BigNumber
const
BigNumber
=
web3
.
BigNumber
...
@@ -15,11 +17,18 @@ contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) {
...
@@ -15,11 +17,18 @@ contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) {
const
rate
=
new
BigNumber
(
1000
)
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
()
{
beforeEach
(
async
function
()
{
this
.
startBlock
=
web3
.
eth
.
blockNumber
+
10
this
.
startTime
=
latestTime
().
unix
()
+
duration
.
weeks
(
1
)
this
.
endBlock
=
web3
.
eth
.
blockNumber
+
20
this
.
endTime
=
this
.
startTime
+
duration
.
weeks
(
1
)
this
.
afterEndTime
=
this
.
endTime
+
duration
.
seconds
(
1
)
this
.
crowdsale
=
await
FinalizableCrowdsale
.
new
(
this
.
start
Block
,
this
.
endBlock
,
rate
,
wallet
,
{
from
:
owner
})
this
.
crowdsale
=
await
FinalizableCrowdsale
.
new
(
this
.
start
Time
,
this
.
endTime
,
rate
,
wallet
,
{
from
:
owner
})
this
.
token
=
MintableToken
.
at
(
await
this
.
crowdsale
.
token
())
this
.
token
=
MintableToken
.
at
(
await
this
.
crowdsale
.
token
())
})
})
...
@@ -29,30 +38,30 @@ contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) {
...
@@ -29,30 +38,30 @@ contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) {
})
})
it
(
'cannot be finalized by third party after ending'
,
async
function
()
{
it
(
'cannot be finalized by third party after ending'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
await
this
.
crowdsale
.
finalize
({
from
:
thirdparty
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
finalize
({
from
:
thirdparty
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
})
})
it
(
'can be finalized by owner after ending'
,
async
function
()
{
it
(
'can be finalized by owner after ending'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
await
this
.
crowdsale
.
finalize
({
from
:
owner
}).
should
.
be
.
fulfilled
await
this
.
crowdsale
.
finalize
({
from
:
owner
}).
should
.
be
.
fulfilled
})
})
it
(
'cannot be finalized twice'
,
async
function
()
{
it
(
'cannot be finalized twice'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
+
1
)
await
increaseTimeTo
(
this
.
afterEndTime
)
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
await
this
.
crowdsale
.
finalize
({
from
:
owner
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
finalize
({
from
:
owner
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
})
})
it
(
'logs finalized'
,
async
function
()
{
it
(
'logs finalized'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
const
{
logs
}
=
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
const
{
logs
}
=
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
const
event
=
logs
.
find
(
e
=>
e
.
event
===
'Finalized'
)
const
event
=
logs
.
find
(
e
=>
e
.
event
===
'Finalized'
)
should
.
exist
(
event
)
should
.
exist
(
event
)
})
})
it
(
'finishes minting of token'
,
async
function
()
{
it
(
'finishes minting of token'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
const
finished
=
await
this
.
token
.
mintingFinished
()
const
finished
=
await
this
.
token
.
mintingFinished
()
finished
.
should
.
equal
(
true
)
finished
.
should
.
equal
(
true
)
...
...
test/RefundableCrowdsale.js
View file @
2b079136
import
ether
from
'./helpers/ether'
import
ether
from
'./helpers/ether'
import
advanceToBlock
from
'./helpers/advanceToBlock'
import
{
advanceBlock
}
from
'./helpers/advanceToBlock'
import
{
increaseTimeTo
,
duration
}
from
'./helpers/increaseTime'
import
latestTime
from
'./helpers/latestTime'
import
EVMThrow
from
'./helpers/EVMThrow'
import
EVMThrow
from
'./helpers/EVMThrow'
const
BigNumber
=
web3
.
BigNumber
const
BigNumber
=
web3
.
BigNumber
...
@@ -17,39 +19,44 @@ contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) {
...
@@ -17,39 +19,44 @@ contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) {
const
goal
=
ether
(
800
)
const
goal
=
ether
(
800
)
const
lessThanGoal
=
ether
(
750
)
const
lessThanGoal
=
ether
(
750
)
describe
(
'creating a valid crowdsale'
,
function
()
{
before
(
async
function
()
{
//Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
it
(
'should fail with zero goal'
,
async
function
()
{
await
advanceBlock
()
await
RefundableCrowdsale
.
new
(
this
.
startBlock
,
this
.
endBlock
,
rate
,
wallet
,
0
,
{
from
:
owner
}).
should
.
be
.
rejectedWith
(
EVMThrow
);
})
})
});
beforeEach
(
async
function
()
{
this
.
startTime
=
latestTime
().
unix
()
+
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
})
})
beforeEach
(
async
function
()
{
describe
(
'creating a valid crowdsale'
,
function
()
{
this
.
startBlock
=
web3
.
eth
.
blockNumber
+
10
this
.
endBlock
=
web3
.
eth
.
blockNumber
+
20
this
.
crowdsale
=
await
RefundableCrowdsale
.
new
(
this
.
startBlock
,
this
.
endBlock
,
rate
,
wallet
,
goal
,
{
from
:
owner
})
it
(
'should fail with zero goal'
,
async
function
()
{
await
RefundableCrowdsale
.
new
(
this
.
startTime
,
this
.
endTime
,
rate
,
wallet
,
0
,
{
from
:
owner
}).
should
.
be
.
rejectedWith
(
EVMThrow
);
})
})
});
it
(
'should deny refunds before end'
,
async
function
()
{
it
(
'should deny refunds before end'
,
async
function
()
{
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
advanceToBlock
(
this
.
endBlock
-
1
)
await
increaseTimeTo
(
this
.
startTime
)
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
})
})
it
(
'should deny refunds after end if goal was reached'
,
async
function
()
{
it
(
'should deny refunds after end if goal was reached'
,
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
-
1
)
await
increaseTimeTo
(
this
.
startTime
)
await
this
.
crowdsale
.
sendTransaction
({
value
:
goal
,
from
:
investor
})
await
this
.
crowdsale
.
sendTransaction
({
value
:
goal
,
from
:
investor
})
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
)
})
})
it
(
'should allow refunds after end if goal was not reached'
,
async
function
()
{
it
(
'should allow refunds after end if goal was not reached'
,
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
-
1
)
await
increaseTimeTo
(
this
.
startTime
)
await
this
.
crowdsale
.
sendTransaction
({
value
:
lessThanGoal
,
from
:
investor
})
await
this
.
crowdsale
.
sendTransaction
({
value
:
lessThanGoal
,
from
:
investor
})
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
...
@@ -62,9 +69,9 @@ contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) {
...
@@ -62,9 +69,9 @@ contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) {
})
})
it
(
'should forward funds to wallet after end if goal was reached'
,
async
function
()
{
it
(
'should forward funds to wallet after end if goal was reached'
,
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
-
1
)
await
increaseTimeTo
(
this
.
startTime
)
await
this
.
crowdsale
.
sendTransaction
({
value
:
goal
,
from
:
investor
})
await
this
.
crowdsale
.
sendTransaction
({
value
:
goal
,
from
:
investor
})
await
advanceToBlock
(
this
.
endBlock
)
await
increaseTimeTo
(
this
.
afterEndTime
)
const
pre
=
web3
.
eth
.
getBalance
(
wallet
)
const
pre
=
web3
.
eth
.
getBalance
(
wallet
)
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
await
this
.
crowdsale
.
finalize
({
from
:
owner
})
...
...
test/SampleCrowdsale.js
View file @
2b079136
import
ether
from
'./helpers/ether'
import
ether
from
'./helpers/ether'
import
advanceToBlock
from
'./helpers/advanceToBlock'
import
{
advanceBlock
}
from
'./helpers/advanceToBlock'
import
{
increaseTimeTo
,
duration
}
from
'./helpers/increaseTime'
import
latestTime
from
'./helpers/latestTime'
import
EVMThrow
from
'./helpers/EVMThrow'
import
EVMThrow
from
'./helpers/EVMThrow'
const
BigNumber
=
web3
.
BigNumber
;
const
BigNumber
=
web3
.
BigNumber
;
...
@@ -18,11 +20,17 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
...
@@ -18,11 +20,17 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
const
GOAL
=
ether
(
10
);
const
GOAL
=
ether
(
10
);
const
CAP
=
ether
(
20
);
const
CAP
=
ether
(
20
);
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
()
{
beforeEach
(
async
function
()
{
this
.
startBlock
=
web3
.
eth
.
blockNumber
+
10
;
this
.
startTime
=
latestTime
().
unix
()
+
duration
.
weeks
(
1
);
this
.
endBlock
=
web3
.
eth
.
blockNumber
+
20
;
this
.
endTime
=
this
.
startTime
+
duration
.
weeks
(
1
);
this
.
afterEndTime
=
this
.
endTime
+
duration
.
seconds
(
1
);
this
.
crowdsale
=
await
SampleCrowdsale
.
new
(
this
.
start
Block
,
this
.
endBlock
,
RATE
,
GOAL
,
CAP
,
wallet
);
this
.
crowdsale
=
await
SampleCrowdsale
.
new
(
this
.
start
Time
,
this
.
endTime
,
RATE
,
GOAL
,
CAP
,
wallet
);
this
.
token
=
SampleCrowdsaleToken
.
at
(
await
this
.
crowdsale
.
token
());
this
.
token
=
SampleCrowdsaleToken
.
at
(
await
this
.
crowdsale
.
token
());
});
});
...
@@ -31,8 +39,8 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
...
@@ -31,8 +39,8 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
this
.
crowdsale
.
should
.
exist
;
this
.
crowdsale
.
should
.
exist
;
this
.
token
.
should
.
exist
;
this
.
token
.
should
.
exist
;
(
await
this
.
crowdsale
.
start
Block
()).
should
.
be
.
bignumber
.
equal
(
this
.
startBlock
);
(
await
this
.
crowdsale
.
start
Time
()).
should
.
be
.
bignumber
.
equal
(
this
.
startTime
);
(
await
this
.
crowdsale
.
end
Block
()).
should
.
be
.
bignumber
.
equal
(
this
.
endBlock
);
(
await
this
.
crowdsale
.
end
Time
()).
should
.
be
.
bignumber
.
equal
(
this
.
endTime
);
(
await
this
.
crowdsale
.
rate
()).
should
.
be
.
bignumber
.
equal
(
RATE
);
(
await
this
.
crowdsale
.
rate
()).
should
.
be
.
bignumber
.
equal
(
RATE
);
(
await
this
.
crowdsale
.
wallet
()).
should
.
be
.
equal
(
wallet
);
(
await
this
.
crowdsale
.
wallet
()).
should
.
be
.
equal
(
wallet
);
(
await
this
.
crowdsale
.
goal
()).
should
.
be
.
bignumber
.
equal
(
GOAL
);
(
await
this
.
crowdsale
.
goal
()).
should
.
be
.
bignumber
.
equal
(
GOAL
);
...
@@ -48,7 +56,7 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
...
@@ -48,7 +56,7 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
const
investmentAmount
=
ether
(
1
);
const
investmentAmount
=
ether
(
1
);
const
expectedTokenAmount
=
RATE
.
mul
(
investmentAmount
);
const
expectedTokenAmount
=
RATE
.
mul
(
investmentAmount
);
await
advanceToBlock
(
this
.
startBlock
-
1
);
await
increaseTimeTo
(
this
.
startTime
);
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
investmentAmount
,
from
:
investor
}).
should
.
be
.
fulfilled
;
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
investmentAmount
,
from
:
investor
}).
should
.
be
.
fulfilled
;
(
await
this
.
token
.
balanceOf
(
investor
)).
should
.
be
.
bignumber
.
equal
(
expectedTokenAmount
);
(
await
this
.
token
.
balanceOf
(
investor
)).
should
.
be
.
bignumber
.
equal
(
expectedTokenAmount
);
...
@@ -56,22 +64,23 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
...
@@ -56,22 +64,23 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
});
});
it
(
'should reject payments after end'
,
async
function
()
{
it
(
'should reject payments after end'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
);
await
increaseTimeTo
(
this
.
afterEnd
);
await
this
.
crowdsale
.
send
(
ether
(
1
)).
should
.
be
.
rejectedWith
(
EVMThrow
);
await
this
.
crowdsale
.
send
(
ether
(
1
)).
should
.
be
.
rejectedWith
(
EVMThrow
);
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
ether
(
1
),
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
);
await
this
.
crowdsale
.
buyTokens
(
investor
,
{
value
:
ether
(
1
),
from
:
investor
}).
should
.
be
.
rejectedWith
(
EVMThrow
);
});
});
it
(
'should reject payments over cap'
,
async
function
()
{
it
(
'should reject payments over cap'
,
async
function
()
{
await
advanceToBlock
(
this
.
startBlock
-
1
);
await
increaseTimeTo
(
this
.
startTime
);
await
this
.
crowdsale
.
send
(
CAP
);
await
this
.
crowdsale
.
send
(
CAP
);
await
this
.
crowdsale
.
send
(
1
).
should
.
be
.
rejectedWith
(
EVMThrow
);
await
this
.
crowdsale
.
send
(
1
).
should
.
be
.
rejectedWith
(
EVMThrow
);
});
});
it
(
'should allow finalization and transfer funds to wallet if the goal is reached'
,
async
function
()
{
it
(
'should allow finalization and transfer funds to wallet if the goal is reached'
,
async
function
()
{
await
advanceToBlock
(
this
.
endBlock
-
1
);
await
increaseTimeTo
(
this
.
startTime
);
await
this
.
crowdsale
.
send
(
GOAL
);
await
this
.
crowdsale
.
send
(
GOAL
);
const
beforeFinalization
=
web3
.
eth
.
getBalance
(
wallet
);
const
beforeFinalization
=
web3
.
eth
.
getBalance
(
wallet
);
await
increaseTimeTo
(
this
.
afterEndTime
);
await
this
.
crowdsale
.
finalize
({
from
:
owner
});
await
this
.
crowdsale
.
finalize
({
from
:
owner
});
const
afterFinalization
=
web3
.
eth
.
getBalance
(
wallet
);
const
afterFinalization
=
web3
.
eth
.
getBalance
(
wallet
);
...
@@ -81,9 +90,9 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
...
@@ -81,9 +90,9 @@ contract('Crowdsale', function ([owner, wallet, investor]) {
it
(
'should allow refunds if the goal is not reached'
,
async
function
()
{
it
(
'should allow refunds if the goal is not reached'
,
async
function
()
{
const
balanceBeforeInvestment
=
web3
.
eth
.
getBalance
(
investor
);
const
balanceBeforeInvestment
=
web3
.
eth
.
getBalance
(
investor
);
await
advanceToBlock
(
this
.
startBlock
-
1
);
await
increaseTimeTo
(
this
.
startTime
);
await
this
.
crowdsale
.
sendTransaction
({
value
:
ether
(
1
),
from
:
investor
,
gasPrice
:
0
});
await
this
.
crowdsale
.
sendTransaction
({
value
:
ether
(
1
),
from
:
investor
,
gasPrice
:
0
});
await
advanceToBlock
(
this
.
endBlock
);
await
increaseTimeTo
(
this
.
afterEndTime
);
await
this
.
crowdsale
.
finalize
({
from
:
owner
});
await
this
.
crowdsale
.
finalize
({
from
:
owner
});
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
,
gasPrice
:
0
}).
should
.
be
.
fulfilled
;
await
this
.
crowdsale
.
claimRefund
({
from
:
investor
,
gasPrice
:
0
}).
should
.
be
.
fulfilled
;
...
...
test/TokenTimelock.js
View file @
2b079136
...
@@ -29,26 +29,26 @@ contract('TokenTimelock', function ([_, owner, beneficiary]) {
...
@@ -29,26 +29,26 @@ contract('TokenTimelock', function ([_, owner, beneficiary]) {
})
})
it
(
'cannot be released just before time limit'
,
async
function
()
{
it
(
'cannot be released just before time limit'
,
async
function
()
{
await
increaseTime
(
moment
.
duration
(
0.99
,
'year'
))
await
increaseTime
(
moment
.
duration
(
0.99
,
'year'
)
.
asSeconds
()
)
await
this
.
timelock
.
release
().
should
.
be
.
rejected
await
this
.
timelock
.
release
().
should
.
be
.
rejected
})
})
it
(
'can be released just after limit'
,
async
function
()
{
it
(
'can be released just after limit'
,
async
function
()
{
await
increaseTime
(
moment
.
duration
(
1.01
,
'year'
))
await
increaseTime
(
moment
.
duration
(
1.01
,
'year'
)
.
asSeconds
()
)
await
this
.
timelock
.
release
().
should
.
be
.
fulfilled
await
this
.
timelock
.
release
().
should
.
be
.
fulfilled
const
balance
=
await
this
.
token
.
balanceOf
(
beneficiary
)
const
balance
=
await
this
.
token
.
balanceOf
(
beneficiary
)
balance
.
should
.
be
.
bignumber
.
equal
(
amount
)
balance
.
should
.
be
.
bignumber
.
equal
(
amount
)
})
})
it
(
'can be released after time limit'
,
async
function
()
{
it
(
'can be released after time limit'
,
async
function
()
{
await
increaseTime
(
moment
.
duration
(
2
,
'year'
))
await
increaseTime
(
moment
.
duration
(
2
,
'year'
)
.
asSeconds
()
)
await
this
.
timelock
.
release
().
should
.
be
.
fulfilled
await
this
.
timelock
.
release
().
should
.
be
.
fulfilled
const
balance
=
await
this
.
token
.
balanceOf
(
beneficiary
)
const
balance
=
await
this
.
token
.
balanceOf
(
beneficiary
)
balance
.
should
.
be
.
bignumber
.
equal
(
amount
)
balance
.
should
.
be
.
bignumber
.
equal
(
amount
)
})
})
it
(
'cannot be released twice'
,
async
function
()
{
it
(
'cannot be released twice'
,
async
function
()
{
await
increaseTime
(
moment
.
duration
(
2
,
'year'
))
await
increaseTime
(
moment
.
duration
(
2
,
'year'
)
.
asSeconds
()
)
await
this
.
timelock
.
release
().
should
.
be
.
fulfilled
await
this
.
timelock
.
release
().
should
.
be
.
fulfilled
await
this
.
timelock
.
release
().
should
.
be
.
rejected
await
this
.
timelock
.
release
().
should
.
be
.
rejected
const
balance
=
await
this
.
token
.
balanceOf
(
beneficiary
)
const
balance
=
await
this
.
token
.
balanceOf
(
beneficiary
)
...
...
test/helpers/CappedCrowdsaleImpl.sol
View file @
2b079136
...
@@ -7,13 +7,13 @@ import '../../contracts/crowdsale/CappedCrowdsale.sol';
...
@@ -7,13 +7,13 @@ import '../../contracts/crowdsale/CappedCrowdsale.sol';
contract CappedCrowdsaleImpl is CappedCrowdsale {
contract CappedCrowdsaleImpl is CappedCrowdsale {
function CappedCrowdsaleImpl (
function CappedCrowdsaleImpl (
uint256 _start
Block
,
uint256 _start
Time
,
uint256 _end
Block
,
uint256 _end
Time
,
uint256 _rate,
uint256 _rate,
address _wallet,
address _wallet,
uint256 _cap
uint256 _cap
)
)
Crowdsale(_start
Block, _endBlock
, _rate, _wallet)
Crowdsale(_start
Time, _endTime
, _rate, _wallet)
CappedCrowdsale(_cap)
CappedCrowdsale(_cap)
{
{
}
}
...
...
test/helpers/FinalizableCrowdsaleImpl.sol
View file @
2b079136
...
@@ -7,12 +7,12 @@ import '../../contracts/crowdsale/FinalizableCrowdsale.sol';
...
@@ -7,12 +7,12 @@ import '../../contracts/crowdsale/FinalizableCrowdsale.sol';
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
function FinalizableCrowdsaleImpl (
function FinalizableCrowdsaleImpl (
uint256 _start
Block
,
uint256 _start
Time
,
uint256 _end
Block
,
uint256 _end
Time
,
uint256 _rate,
uint256 _rate,
address _wallet
address _wallet
)
)
Crowdsale(_start
Block, _endBlock
, _rate, _wallet)
Crowdsale(_start
Time, _endTime
, _rate, _wallet)
FinalizableCrowdsale()
FinalizableCrowdsale()
{
{
}
}
...
...
test/helpers/RefundableCrowdsaleImpl.sol
View file @
2b079136
...
@@ -7,13 +7,13 @@ import '../../contracts/crowdsale/RefundableCrowdsale.sol';
...
@@ -7,13 +7,13 @@ import '../../contracts/crowdsale/RefundableCrowdsale.sol';
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
function RefundableCrowdsaleImpl (
function RefundableCrowdsaleImpl (
uint256 _start
Block
,
uint256 _start
Time
,
uint256 _end
Block
,
uint256 _end
Time
,
uint256 _rate,
uint256 _rate,
address _wallet,
address _wallet,
uint256 _goal
uint256 _goal
)
)
Crowdsale(_start
Block, _endBlock
, _rate, _wallet)
Crowdsale(_start
Time, _endTime
, _rate, _wallet)
RefundableCrowdsale(_goal)
RefundableCrowdsale(_goal)
{
{
}
}
...
...
test/helpers/increaseTime.js
View file @
2b079136
// Increases testrpc time by the passed duration (a moment.js instance)
import
latestTime
from
'./latestTime'
// Increases testrpc time by the passed duration in seconds
export
default
function
increaseTime
(
duration
)
{
export
default
function
increaseTime
(
duration
)
{
const
id
=
Date
.
now
()
const
id
=
Date
.
now
()
...
@@ -6,7 +8,7 @@ export default function increaseTime(duration) {
...
@@ -6,7 +8,7 @@ export default function increaseTime(duration) {
web3
.
currentProvider
.
sendAsync
({
web3
.
currentProvider
.
sendAsync
({
jsonrpc
:
'2.0'
,
jsonrpc
:
'2.0'
,
method
:
'evm_increaseTime'
,
method
:
'evm_increaseTime'
,
params
:
[
duration
.
asSeconds
()
],
params
:
[
duration
],
id
:
id
,
id
:
id
,
},
err1
=>
{
},
err1
=>
{
if
(
err1
)
return
reject
(
err1
)
if
(
err1
)
return
reject
(
err1
)
...
@@ -21,3 +23,25 @@ export default function increaseTime(duration) {
...
@@ -21,3 +23,25 @@ export default function increaseTime(duration) {
})
})
})
})
}
}
/**
* Beware that due to the need of calling two separate testrpc methods and rpc calls overhead
* it's hard to increase time precisely to a target point so design your test to tolerate
* small fluctuations from time to time.
*
* @param target time in seconds
*/
export
function
increaseTimeTo
(
target
)
{
let
now
=
latestTime
().
unix
();
if
(
target
<
now
)
throw
Error
(
`Cannot increase current time(
${
now
}
) to a moment in the past(
${
target
}
)`
);
let
diff
=
target
-
now
;
return
increaseTime
(
diff
);
}
export
const
duration
=
{
seconds
:
function
(
val
)
{
return
val
},
minutes
:
function
(
val
)
{
return
val
*
this
.
seconds
(
60
)
},
hours
:
function
(
val
)
{
return
val
*
this
.
minutes
(
60
)
},
days
:
function
(
val
)
{
return
val
*
this
.
hours
(
24
)
},
weeks
:
function
(
val
)
{
return
val
*
this
.
days
(
7
)
}
};
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment