Compare commits

...

54 Commits

Author SHA1 Message Date
6e070c91e8 1.9.1 2018-05-22 21:01:40 -03:00
59afaca753 remove distribution and kernel from zos.ropsten.json 2018-05-22 20:06:15 -03:00
f35eeed0eb freeze rinkeby version 2018-05-22 19:28:38 -03:00
8b19e3c215 fix linter errors 2018-05-22 19:21:52 -03:00
dca62efba9 add correct zos.ropsten.json 2018-05-22 19:11:41 -03:00
923bbb44a8 add zos files to npm package 2018-05-22 18:43:38 -03:00
d4c455c180 rename livenet to mainnet 2018-05-22 18:43:16 -03:00
5ac618681a add zos.rinkeby.json 2018-05-22 18:30:55 -03:00
d191247505 add full zos.livenet.json 2018-05-22 17:30:14 -03:00
9b55e96fa0 add partial zos.livenet.json 2018-05-22 17:30:14 -03:00
8868c0b6d3 update to zos-cli 0.8.0 2018-05-22 16:27:45 -03:00
534ff92ba5 add zos-lib as peerdependency 2018-05-22 16:09:41 -03:00
31ec824aef Revert "add workaround because truffle doesn't support transitive dependencies"
This reverts commit 48a7cd4e60.
2018-05-22 16:07:27 -03:00
b732b6417e bump to 1.9.0 2018-05-22 14:57:33 -03:00
998b5f43fb update zos to 0.7.0 2018-05-21 18:46:32 -03:00
ff31995104 update zos-lib to latest version 2018-05-21 15:58:05 -03:00
48a7cd4e60 add workaround because truffle doesn't support transitive dependencies 2018-05-21 15:54:35 -03:00
acd34a9372 fix bug in DetailedPremintedToken 2018-05-21 15:26:44 -03:00
2ce67a25ef add more contracts from openzeppelin-solidity 2018-05-21 15:26:44 -03:00
700b811813 fix linter errors and warnings 2018-05-21 15:26:44 -03:00
16f04b13d7 revert truffle-config.js changes from 95fdc7b 2018-05-21 15:26:44 -03:00
e3ad4a5e14 remove unnecessary sender arguments 2018-05-21 15:26:28 -03:00
579446d5d9 Fixed MintableToken's initialize not being called. 2018-05-19 01:02:12 -03:00
fc07f7a0ff RBACWithAdmin now has an initialize function instead of a constructor. 2018-05-19 00:58:52 -03:00
dd6054efeb remove unnecessary sender arguments 2018-05-18 21:45:45 -03:00
27a6a15d66 add explicit initializers 2018-05-18 21:45:34 -03:00
32e93579fa added package.zos files 2018-05-18 21:44:56 -03:00
c8719ce418 fix initialize versions 2018-05-18 21:44:08 -03:00
39fe05dfad add more openzeppelin-solidity library contracts 2018-05-18 21:44:08 -03:00
be101154fa update to newer zos.json format 2018-05-18 21:21:37 -03:00
c329fc0a5f update zos to latest version 2018-05-18 21:01:23 -03:00
e55dbc9681 update to latest zos and zos-lib 2018-05-18 19:07:15 -03:00
6f1c67af0d commit new package-lock.json format generated by npm 6 2018-05-18 18:55:24 -03:00
5284a6df88 update nan 2.6.2 -> 2.10.0 for node 10 compatibility 2018-05-18 18:19:15 -03:00
8bce0a4f2e update sha3 1.2.0 -> 1.2.2 for node 10 compatibility 2018-05-18 18:19:12 -03:00
11d2bbc092 Merge tag 'v1.9.0' into zos-release
1.9.0
2018-05-17 20:04:00 -03:00
ff69c54497 move zos (cli) to devDependency 2018-04-20 22:47:38 -03:00
6669f3fcee Merge branch 'zos-release' of github.com:OpenZeppelin/zeppelin-solidity into zos-release 2018-04-20 21:37:28 -03:00
18e16a5db0 added package.zos 2018-04-20 20:38:23 -03:00
95fdc7bd8a update contracts and config 2018-04-20 19:58:16 -03:00
27d696aa7d add deployable erc20 contracts 2018-04-20 13:31:27 -03:00
ff6a565452 bump version 2018-04-20 13:31:27 -03:00
5f079c8605 add prepack step to build contracts 2018-04-20 13:31:27 -03:00
ea335ebc64 ignore everything but official contracts for npm 2018-04-20 13:31:27 -03:00
b1a801566c fix initializers and tests 2018-04-20 13:31:26 -03:00
2eac2a79b7 add mintable erc721 token 2018-04-20 13:30:22 -03:00
f9fc8d2e96 adapt contracts for upgradeability 2018-04-20 13:29:50 -03:00
89c32f5dd7 delete contracts and tests not yet in zos 2018-04-20 12:18:08 -03:00
eff3d7ca8e bump version 2018-04-20 11:38:48 -03:00
85225ef6ae add mintable erc721 token 2018-04-20 11:38:48 -03:00
2010c6b464 add prepack step to build contracts 2018-04-19 12:32:56 -03:00
03891b00a7 ignore everything but official contracts for npm 2018-04-19 12:26:30 -03:00
d0ec491b1f adapt contracts for upgradeability 2018-04-18 18:10:53 -03:00
38536f42f4 delete contracts and tests not yet in zos 2018-04-18 18:10:53 -03:00
124 changed files with 5777 additions and 7018 deletions

View File

@ -1,72 +0,0 @@
pragma solidity ^0.4.21;
import "./payment/PullPayment.sol";
import "./lifecycle/Destructible.sol";
/**
* @title Bounty
* @dev This bounty will pay out to a researcher if they break invariant logic of the contract.
*/
contract Bounty is PullPayment, Destructible {
bool public claimed;
mapping(address => address) public researchers;
event TargetCreated(address createdAddress);
/**
* @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed.
*/
function() external payable {
require(!claimed);
}
/**
* @dev Create and deploy the target contract (extension of Target contract), and sets the
* msg.sender as a researcher
* @return A target contract
*/
function createTarget() public returns(Target) {
Target target = Target(deployContract());
researchers[target] = msg.sender;
emit TargetCreated(target);
return target;
}
/**
* @dev Sends the contract funds to the researcher that proved the contract is broken.
* @param target contract
*/
function claim(Target target) public {
address researcher = researchers[target];
require(researcher != 0);
// Check Target contract invariants
require(!target.checkInvariant());
asyncSend(researcher, address(this).balance);
claimed = true;
}
/**
* @dev Internal function to deploy the target contract.
* @return A target contract address
*/
function deployContract() internal returns(address);
}
/**
* @title Target
* @dev Your main contract should inherit from this class and implement the checkInvariant method.
*/
contract Target {
/**
* @dev Checks all values a contract assumes to be true all the time. If this function returns
* false, the contract is broken in some way and is in an inconsistent state.
* In order to win the bounty, security researchers will try to cause this broken state.
* @return True if all invariant values are correct, false otherwise.
*/
function checkInvariant() public returns(bool);
}

View File

@ -1,75 +0,0 @@
pragma solidity ^0.4.21;
/**
* @title DayLimit
* @dev Base contract that enables methods to be protected by placing a linear limit (specifiable)
* on a particular resource per calendar day. Is multiowned to allow the limit to be altered.
*/
contract DayLimit {
uint256 public dailyLimit;
uint256 public spentToday;
uint256 public lastDay;
/**
* @dev Constructor that sets the passed value as a dailyLimit.
* @param _limit uint256 to represent the daily limit.
*/
function DayLimit(uint256 _limit) public {
dailyLimit = _limit;
lastDay = today();
}
/**
* @dev sets the daily limit. Does not alter the amount already spent today.
* @param _newLimit uint256 to represent the new limit.
*/
function _setDailyLimit(uint256 _newLimit) internal {
dailyLimit = _newLimit;
}
/**
* @dev Resets the amount already spent today.
*/
function _resetSpentToday() internal {
spentToday = 0;
}
/**
* @dev Checks to see if there is enough resource to spend today. If true, the resource may be expended.
* @param _value uint256 representing the amount of resource to spend.
* @return A boolean that is True if the resource was spent and false otherwise.
*/
function underLimit(uint256 _value) internal returns (bool) {
// reset the spend limit if we're on a different day to last time.
if (today() > lastDay) {
spentToday = 0;
lastDay = today();
}
// check to see if there's enough left - if so, subtract and return true.
// overflow protection // dailyLimit check
if (spentToday + _value >= spentToday && spentToday + _value <= dailyLimit) {
spentToday += _value;
return true;
}
return false;
}
/**
* @dev Private function to determine today's index
* @return uint256 of today's index.
*/
function today() private view returns (uint256) {
// solium-disable-next-line security/no-block-members
return block.timestamp / 1 days;
}
/**
* @dev Simple modifier for daily limit.
*/
modifier limitedDaily(uint256 _value) {
require(underLimit(_value));
_;
}
}

View File

@ -1,31 +0,0 @@
pragma solidity ^0.4.21;
/**
* @title LimitBalance
* @dev Simple contract to limit the balance of child contract.
* @dev Note this doesn't prevent other contracts to send funds by using selfdestruct(address);
* @dev See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account
*/
contract LimitBalance {
uint256 public limit;
/**
* @dev Constructor that sets the passed value as a limit.
* @param _limit uint256 to represent the limit.
*/
function LimitBalance(uint256 _limit) public {
limit = _limit;
}
/**
* @dev Checks if limit was reached. Case true, it throws.
*/
modifier limitedPayable() {
require(address(this).balance <= limit);
_;
}
}

View File

@ -1,32 +0,0 @@
pragma solidity ^0.4.21;
/**
* @title Helps contracts guard agains reentrancy attacks.
* @author Remco Bloemen <remco@2π.com>
* @notice If you mark a function `nonReentrant`, you should also
* mark it `external`.
*/
contract ReentrancyGuard {
/**
* @dev We use a single lock for the whole contract.
*/
bool private reentrancyLock = false;
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* @notice If you mark a function `nonReentrant`, you should also
* mark it `external`. Calling one nonReentrant function from
* another is not supported. Instead, you can implement a
* `private` function doing the actual work, and a `external`
* wrapper marked as `nonReentrant`.
*/
modifier nonReentrant() {
require(!reentrancyLock);
reentrancyLock = true;
_;
reentrancyLock = false;
}
}

View File

@ -4,6 +4,7 @@ import "../ownership/Ownable.sol";
import "../ownership/rbac/RBAC.sol";
import "../ECRecovery.sol";
/**
* @title SignatureBouncer
* @author PhABC and Shrugs
@ -21,11 +22,18 @@ import "../ECRecovery.sol";
* @dev
* @dev See the tests Bouncer.test.js for specific usage examples.
*/
contract SignatureBouncer is Ownable, RBAC {
contract SignatureBouncer is Migratable, Ownable, RBAC {
using ECRecovery for bytes32;
string public constant ROLE_BOUNCER = "bouncer";
function initialize(address _sender)
isInitializer("SignatureBouncer", "1.9.0")
public
{
Ownable.initialize(_sender);
}
/**
* @dev requires that a valid signature of a bouncer was provided
*/

View File

@ -1,163 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/ERC20.sol";
import "../math/SafeMath.sol";
/**
* @title Crowdsale
* @dev Crowdsale is a base contract for managing a token crowdsale,
* allowing investors to purchase tokens with ether. This contract implements
* such functionality in its most fundamental form and can be extended to provide additional
* functionality and/or custom behavior.
* The external interface represents the basic interface for purchasing tokens, and conform
* the base architecture for crowdsales. They are *not* intended to be modified / overriden.
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override
* the methods to add functionality. Consider using 'super' where appropiate to concatenate
* behavior.
*/
contract Crowdsale {
using SafeMath for uint256;
// The token being sold
ERC20 public token;
// Address where funds are collected
address public wallet;
// How many token units a buyer gets per wei
uint256 public rate;
// Amount of wei raised
uint256 public weiRaised;
/**
* Event for token purchase logging
* @param purchaser who paid for the tokens
* @param beneficiary who got the tokens
* @param value weis paid for purchase
* @param amount amount of tokens purchased
*/
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
/**
* @param _rate Number of token units a buyer gets per wei
* @param _wallet Address where collected funds will be forwarded to
* @param _token Address of the token being sold
*/
function Crowdsale(uint256 _rate, address _wallet, ERC20 _token) public {
require(_rate > 0);
require(_wallet != address(0));
require(_token != address(0));
rate = _rate;
wallet = _wallet;
token = _token;
}
// -----------------------------------------
// Crowdsale external interface
// -----------------------------------------
/**
* @dev fallback function ***DO NOT OVERRIDE***
*/
function () external payable {
buyTokens(msg.sender);
}
/**
* @dev low level token purchase ***DO NOT OVERRIDE***
* @param _beneficiary Address performing the token purchase
*/
function buyTokens(address _beneficiary) public payable {
uint256 weiAmount = msg.value;
_preValidatePurchase(_beneficiary, weiAmount);
// calculate token amount to be created
uint256 tokens = _getTokenAmount(weiAmount);
// update state
weiRaised = weiRaised.add(weiAmount);
_processPurchase(_beneficiary, tokens);
emit TokenPurchase(
msg.sender,
_beneficiary,
weiAmount,
tokens
);
_updatePurchasingState(_beneficiary, weiAmount);
_forwardFunds();
_postValidatePurchase(_beneficiary, weiAmount);
}
// -----------------------------------------
// Internal interface (extensible)
// -----------------------------------------
/**
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
require(_beneficiary != address(0));
require(_weiAmount != 0);
}
/**
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _postValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
// optional override
}
/**
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
* @param _beneficiary Address performing the token purchase
* @param _tokenAmount Number of tokens to be emitted
*/
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
token.transfer(_beneficiary, _tokenAmount);
}
/**
* @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
* @param _beneficiary Address receiving the tokens
* @param _tokenAmount Number of tokens to be purchased
*/
function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
_deliverTokens(_beneficiary, _tokenAmount);
}
/**
* @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
* @param _beneficiary Address receiving the tokens
* @param _weiAmount Value in wei involved in the purchase
*/
function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
// optional override
}
/**
* @dev Override to extend the way in which ether is converted to tokens.
* @param _weiAmount Value in wei to be converted into tokens
* @return Number of tokens that can be purchased with the specified _weiAmount
*/
function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
return _weiAmount.mul(rate);
}
/**
* @dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds() internal {
wallet.transfer(msg.value);
}
}

View File

@ -1,42 +0,0 @@
pragma solidity ^0.4.21;
import "../../math/SafeMath.sol";
import "../../ownership/Ownable.sol";
import "../validation/TimedCrowdsale.sol";
/**
* @title FinalizableCrowdsale
* @dev Extension of Crowdsale where an owner can do extra work
* after finishing.
*/
contract FinalizableCrowdsale is TimedCrowdsale, Ownable {
using SafeMath for uint256;
bool public isFinalized = false;
event Finalized();
/**
* @dev Must be called after crowdsale ends, to do some extra finalization
* work. Calls the contract's finalization function.
*/
function finalize() onlyOwner public {
require(!isFinalized);
require(hasClosed());
finalization();
emit Finalized();
isFinalized = true;
}
/**
* @dev Can be overridden to add finalization logic. The overriding function
* should call super.finalization() to ensure the chain of finalization is
* executed entirely.
*/
function finalization() internal {
}
}

View File

@ -1,37 +0,0 @@
pragma solidity ^0.4.21;
import "../validation/TimedCrowdsale.sol";
import "../../token/ERC20/ERC20.sol";
import "../../math/SafeMath.sol";
/**
* @title PostDeliveryCrowdsale
* @dev Crowdsale that locks tokens from withdrawal until it ends.
*/
contract PostDeliveryCrowdsale is TimedCrowdsale {
using SafeMath for uint256;
mapping(address => uint256) public balances;
/**
* @dev Withdraw tokens only after crowdsale ends.
*/
function withdrawTokens() public {
require(hasClosed());
uint256 amount = balances[msg.sender];
require(amount > 0);
balances[msg.sender] = 0;
_deliverTokens(msg.sender, amount);
}
/**
* @dev Overrides parent by storing balances instead of issuing tokens right away.
* @param _beneficiary Token purchaser
* @param _tokenAmount Amount of tokens purchased
*/
function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
balances[_beneficiary] = balances[_beneficiary].add(_tokenAmount);
}
}

View File

@ -1,72 +0,0 @@
pragma solidity ^0.4.21;
import "../../math/SafeMath.sol";
import "./FinalizableCrowdsale.sol";
import "./utils/RefundVault.sol";
/**
* @title RefundableCrowdsale
* @dev Extension of Crowdsale contract that adds a funding goal, and
* the possibility of users getting a refund if goal is not met.
* Uses a RefundVault as the crowdsale's vault.
*/
contract RefundableCrowdsale is FinalizableCrowdsale {
using SafeMath for uint256;
// minimum amount of funds to be raised in weis
uint256 public goal;
// refund vault used to hold funds while crowdsale is running
RefundVault public vault;
/**
* @dev Constructor, creates RefundVault.
* @param _goal Funding goal
*/
function RefundableCrowdsale(uint256 _goal) public {
require(_goal > 0);
vault = new RefundVault(wallet);
goal = _goal;
}
/**
* @dev Investors can claim refunds here if crowdsale is unsuccessful
*/
function claimRefund() public {
require(isFinalized);
require(!goalReached());
vault.refund(msg.sender);
}
/**
* @dev Checks whether funding goal was reached.
* @return Whether funding goal was reached
*/
function goalReached() public view returns (bool) {
return weiRaised >= goal;
}
/**
* @dev vault finalization task, called when owner calls finalize()
*/
function finalization() internal {
if (goalReached()) {
vault.close();
} else {
vault.enableRefunds();
}
super.finalization();
}
/**
* @dev Overrides Crowdsale fund forwarding, sending funds to vault.
*/
function _forwardFunds() internal {
vault.deposit.value(msg.value)(msg.sender);
}
}

View File

@ -1,66 +0,0 @@
pragma solidity ^0.4.21;
import "../../../math/SafeMath.sol";
import "../../../ownership/Ownable.sol";
/**
* @title RefundVault
* @dev This contract is used for storing funds while a crowdsale
* is in progress. Supports refunding the money if crowdsale fails,
* and forwarding it if crowdsale is successful.
*/
contract RefundVault is Ownable {
using SafeMath for uint256;
enum State { Active, Refunding, Closed }
mapping (address => uint256) public deposited;
address public wallet;
State public state;
event Closed();
event RefundsEnabled();
event Refunded(address indexed beneficiary, uint256 weiAmount);
/**
* @param _wallet Vault address
*/
function RefundVault(address _wallet) public {
require(_wallet != address(0));
wallet = _wallet;
state = State.Active;
}
/**
* @param investor Investor address
*/
function deposit(address investor) onlyOwner public payable {
require(state == State.Active);
deposited[investor] = deposited[investor].add(msg.value);
}
function close() onlyOwner public {
require(state == State.Active);
state = State.Closed;
emit Closed();
wallet.transfer(address(this).balance);
}
function enableRefunds() onlyOwner public {
require(state == State.Active);
state = State.Refunding;
emit RefundsEnabled();
}
/**
* @param investor Investor address
*/
function refund(address investor) public {
require(state == State.Refunding);
uint256 depositedValue = deposited[investor];
deposited[investor] = 0;
investor.transfer(depositedValue);
emit Refunded(investor, depositedValue);
}
}

View File

@ -1,42 +0,0 @@
pragma solidity ^0.4.21;
import "../Crowdsale.sol";
import "../../token/ERC20/ERC20.sol";
import "../../math/SafeMath.sol";
/**
* @title AllowanceCrowdsale
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
*/
contract AllowanceCrowdsale is Crowdsale {
using SafeMath for uint256;
address public tokenWallet;
/**
* @dev Constructor, takes token wallet address.
* @param _tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
*/
function AllowanceCrowdsale(address _tokenWallet) public {
require(_tokenWallet != address(0));
tokenWallet = _tokenWallet;
}
/**
* @dev Checks the amount of tokens left in the allowance.
* @return Amount of tokens left in the allowance
*/
function remainingTokens() public view returns (uint256) {
return token.allowance(tokenWallet, this);
}
/**
* @dev Overrides parent behavior by transferring tokens from wallet.
* @param _beneficiary Token purchaser
* @param _tokenAmount Amount of tokens purchased
*/
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
token.transferFrom(tokenWallet, _beneficiary, _tokenAmount);
}
}

View File

@ -1,22 +0,0 @@
pragma solidity ^0.4.21;
import "../Crowdsale.sol";
import "../../token/ERC20/MintableToken.sol";
/**
* @title MintedCrowdsale
* @dev Extension of Crowdsale contract whose tokens are minted in each purchase.
* Token ownership should be transferred to MintedCrowdsale for minting.
*/
contract MintedCrowdsale is Crowdsale {
/**
* @dev Overrides delivery by minting tokens upon purchase.
* @param _beneficiary Token purchaser
* @param _tokenAmount Number of tokens to be minted
*/
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
require(MintableToken(token).mint(_beneficiary, _tokenAmount));
}
}

View File

@ -1,54 +0,0 @@
pragma solidity ^0.4.21;
import "../validation/TimedCrowdsale.sol";
import "../../math/SafeMath.sol";
/**
* @title IncreasingPriceCrowdsale
* @dev Extension of Crowdsale contract that increases the price of tokens linearly in time.
* Note that what should be provided to the constructor is the initial and final _rates_, that is,
* the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate.
*/
contract IncreasingPriceCrowdsale is TimedCrowdsale {
using SafeMath for uint256;
uint256 public initialRate;
uint256 public finalRate;
/**
* @dev Constructor, takes intial and final rates of tokens received per wei contributed.
* @param _initialRate Number of tokens a buyer gets per wei at the start of the crowdsale
* @param _finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
*/
function IncreasingPriceCrowdsale(uint256 _initialRate, uint256 _finalRate) public {
require(_initialRate >= _finalRate);
require(_finalRate > 0);
initialRate = _initialRate;
finalRate = _finalRate;
}
/**
* @dev Returns the rate of tokens per wei at the present time.
* Note that, as price _increases_ with time, the rate _decreases_.
* @return The number of tokens a buyer gets per wei at a given time
*/
function getCurrentRate() public view returns (uint256) {
// solium-disable-next-line security/no-block-members
uint256 elapsedTime = block.timestamp.sub(openingTime);
uint256 timeRange = closingTime.sub(openingTime);
uint256 rateRange = initialRate.sub(finalRate);
return initialRate.sub(elapsedTime.mul(rateRange).div(timeRange));
}
/**
* @dev Overrides parent method taking into account variable rate.
* @param _weiAmount The value in wei to be converted into tokens
* @return The number of tokens _weiAmount wei will buy at present time
*/
function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
uint256 currentRate = getCurrentRate();
return currentRate.mul(_weiAmount);
}
}

View File

@ -1,43 +0,0 @@
pragma solidity ^0.4.21;
import "../../math/SafeMath.sol";
import "../Crowdsale.sol";
/**
* @title CappedCrowdsale
* @dev Crowdsale with a limit for total contributions.
*/
contract CappedCrowdsale is Crowdsale {
using SafeMath for uint256;
uint256 public cap;
/**
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
* @param _cap Max amount of wei to be contributed
*/
function CappedCrowdsale(uint256 _cap) public {
require(_cap > 0);
cap = _cap;
}
/**
* @dev Checks whether the cap has been reached.
* @return Whether the cap was reached
*/
function capReached() public view returns (bool) {
return weiRaised >= cap;
}
/**
* @dev Extend parent behavior requiring purchase to respect the funding cap.
* @param _beneficiary Token purchaser
* @param _weiAmount Amount of wei contributed
*/
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
super._preValidatePurchase(_beneficiary, _weiAmount);
require(weiRaised.add(_weiAmount) <= cap);
}
}

View File

@ -1,76 +0,0 @@
pragma solidity ^0.4.21;
import "../../math/SafeMath.sol";
import "../Crowdsale.sol";
import "../../ownership/Ownable.sol";
/**
* @title IndividuallyCappedCrowdsale
* @dev Crowdsale with per-user caps.
*/
contract IndividuallyCappedCrowdsale is Crowdsale, Ownable {
using SafeMath for uint256;
mapping(address => uint256) public contributions;
mapping(address => uint256) public caps;
/**
* @dev Sets a specific user's maximum contribution.
* @param _beneficiary Address to be capped
* @param _cap Wei limit for individual contribution
*/
function setUserCap(address _beneficiary, uint256 _cap) external onlyOwner {
caps[_beneficiary] = _cap;
}
/**
* @dev Sets a group of users' maximum contribution.
* @param _beneficiaries List of addresses to be capped
* @param _cap Wei limit for individual contribution
*/
function setGroupCap(address[] _beneficiaries, uint256 _cap) external onlyOwner {
for (uint256 i = 0; i < _beneficiaries.length; i++) {
caps[_beneficiaries[i]] = _cap;
}
}
/**
* @dev Returns the cap of a specific user.
* @param _beneficiary Address whose cap is to be checked
* @return Current cap for individual user
*/
function getUserCap(address _beneficiary) public view returns (uint256) {
return caps[_beneficiary];
}
/**
* @dev Returns the amount contributed so far by a sepecific user.
* @param _beneficiary Address of contributor
* @return User contribution so far
*/
function getUserContribution(address _beneficiary) public view returns (uint256) {
return contributions[_beneficiary];
}
/**
* @dev Extend parent behavior requiring purchase to respect the user's funding cap.
* @param _beneficiary Token purchaser
* @param _weiAmount Amount of wei contributed
*/
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
super._preValidatePurchase(_beneficiary, _weiAmount);
require(contributions[_beneficiary].add(_weiAmount) <= caps[_beneficiary]);
}
/**
* @dev Extend parent behavior to update user contributions
* @param _beneficiary Token purchaser
* @param _weiAmount Amount of wei contributed
*/
function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
super._updatePurchasingState(_beneficiary, _weiAmount);
contributions[_beneficiary] = contributions[_beneficiary].add(_weiAmount);
}
}

View File

@ -1,58 +0,0 @@
pragma solidity ^0.4.21;
import "../../math/SafeMath.sol";
import "../Crowdsale.sol";
/**
* @title TimedCrowdsale
* @dev Crowdsale accepting contributions only within a time frame.
*/
contract TimedCrowdsale is Crowdsale {
using SafeMath for uint256;
uint256 public openingTime;
uint256 public closingTime;
/**
* @dev Reverts if not in crowdsale time range.
*/
modifier onlyWhileOpen {
// solium-disable-next-line security/no-block-members
require(block.timestamp >= openingTime && block.timestamp <= closingTime);
_;
}
/**
* @dev Constructor, takes crowdsale opening and closing times.
* @param _openingTime Crowdsale opening time
* @param _closingTime Crowdsale closing time
*/
function TimedCrowdsale(uint256 _openingTime, uint256 _closingTime) public {
// solium-disable-next-line security/no-block-members
require(_openingTime >= block.timestamp);
require(_closingTime >= _openingTime);
openingTime = _openingTime;
closingTime = _closingTime;
}
/**
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
* @return Whether crowdsale period has elapsed
*/
function hasClosed() public view returns (bool) {
// solium-disable-next-line security/no-block-members
return block.timestamp > closingTime;
}
/**
* @dev Extend parent behavior requiring to be within contributing period
* @param _beneficiary Token purchaser
* @param _weiAmount Amount of wei contributed
*/
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal onlyWhileOpen {
super._preValidatePurchase(_beneficiary, _weiAmount);
}
}

View File

@ -1,58 +0,0 @@
pragma solidity ^0.4.21;
import "../Crowdsale.sol";
import "../../ownership/Ownable.sol";
/**
* @title WhitelistedCrowdsale
* @dev Crowdsale in which only whitelisted users can contribute.
*/
contract WhitelistedCrowdsale is Crowdsale, Ownable {
mapping(address => bool) public whitelist;
/**
* @dev Reverts if beneficiary is not whitelisted. Can be used when extending this contract.
*/
modifier isWhitelisted(address _beneficiary) {
require(whitelist[_beneficiary]);
_;
}
/**
* @dev Adds single address to whitelist.
* @param _beneficiary Address to be added to the whitelist
*/
function addToWhitelist(address _beneficiary) external onlyOwner {
whitelist[_beneficiary] = true;
}
/**
* @dev Adds list of addresses to whitelist. Not overloaded due to limitations with truffle testing.
* @param _beneficiaries Addresses to be added to the whitelist
*/
function addManyToWhitelist(address[] _beneficiaries) external onlyOwner {
for (uint256 i = 0; i < _beneficiaries.length; i++) {
whitelist[_beneficiaries[i]] = true;
}
}
/**
* @dev Removes single address from whitelist.
* @param _beneficiary Address to be removed to the whitelist
*/
function removeFromWhitelist(address _beneficiary) external onlyOwner {
whitelist[_beneficiary] = false;
}
/**
* @dev Extend parent behavior requiring beneficiary to be in whitelist.
* @param _beneficiary Token beneficiary
* @param _weiAmount Amount of wei contributed
*/
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal isWhitelisted(_beneficiary) {
super._preValidatePurchase(_beneficiary, _weiAmount);
}
}

View File

@ -1,55 +0,0 @@
pragma solidity ^0.4.21;
import "../crowdsale/validation/CappedCrowdsale.sol";
import "../crowdsale/distribution/RefundableCrowdsale.sol";
import "../crowdsale/emission/MintedCrowdsale.sol";
import "../token/ERC20/MintableToken.sol";
/**
* @title SampleCrowdsaleToken
* @dev Very simple ERC20 Token that can be minted.
* It is meant to be used in a crowdsale contract.
*/
contract SampleCrowdsaleToken is MintableToken {
string public constant name = "Sample Crowdsale Token"; // solium-disable-line uppercase
string public constant symbol = "SCT"; // solium-disable-line uppercase
uint8 public constant decimals = 18; // solium-disable-line uppercase
}
/**
* @title SampleCrowdsale
* @dev This is an example of a fully fledged crowdsale.
* The way to add new features to a base crowdsale is by multiple inheritance.
* In this example we are providing following extensions:
* CappedCrowdsale - sets a max boundary for raised funds
* RefundableCrowdsale - set a min goal to be reached and returns funds if it's not met
*
* After adding multiple features it's good practice to run integration tests
* to ensure that subcontracts works together as intended.
*/
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {
function SampleCrowdsale(
uint256 _openingTime,
uint256 _closingTime,
uint256 _rate,
address _wallet,
uint256 _cap,
MintableToken _token,
uint256 _goal
)
public
Crowdsale(_rate, _wallet, _token)
CappedCrowdsale(_cap)
TimedCrowdsale(_openingTime, _closingTime)
RefundableCrowdsale(_goal)
{
//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
require(_goal <= _cap);
}
}

View File

@ -1,40 +0,0 @@
pragma solidity ^0.4.21;
import "../ownership/Heritable.sol";
/**
* @title SimpleSavingsWallet
* @dev Simplest form of savings wallet whose ownership can be claimed by a heir
* if owner dies.
* In this example, we take a very simple savings wallet providing two operations
* (to send and receive funds) and extend its capabilities by making it Heritable.
* The account that creates the contract is set as owner, who has the authority to
* choose an heir account. Heir account can reclaim the contract ownership in the
* case that the owner dies.
*/
contract SimpleSavingsWallet is Heritable {
event Sent(address indexed payee, uint256 amount, uint256 balance);
event Received(address indexed payer, uint256 amount, uint256 balance);
function SimpleSavingsWallet(uint256 _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}
/**
* @dev wallet can receive funds.
*/
function () public payable {
emit Received(msg.sender, msg.value, address(this).balance);
}
/**
* @dev wallet can send funds
*/
function sendTo(address payee, uint256 amount) public onlyOwner {
require(payee != 0 && payee != address(this));
require(amount > 0);
payee.transfer(amount);
emit Sent(payee, amount, address(this).balance);
}
}

View File

@ -1,30 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/StandardToken.sol";
/**
* @title SimpleToken
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
* Note they can later distribute these tokens as they wish using `transfer` and other
* `StandardToken` functions.
*/
contract SimpleToken is StandardToken {
string public constant name = "SimpleToken"; // solium-disable-line uppercase
string public constant symbol = "SIM"; // solium-disable-line uppercase
uint8 public constant decimals = 18; // solium-disable-line uppercase
uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals));
/**
* @dev Constructor that gives msg.sender all of existing tokens.
*/
function SimpleToken() public {
totalSupply_ = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
emit Transfer(0x0, msg.sender, INITIAL_SUPPLY);
}
}

View File

@ -1,25 +0,0 @@
pragma solidity ^0.4.21;
import "../ownership/Ownable.sol";
/**
* @title Destructible
* @dev Base contract that can be destroyed by owner. All funds in contract will be sent to the owner.
*/
contract Destructible is Ownable {
function Destructible() public payable { }
/**
* @dev Transfers the current balance to the owner and terminates the contract.
*/
function destroy() onlyOwner public {
selfdestruct(owner);
}
function destroyAndSend(address _recipient) onlyOwner public {
selfdestruct(_recipient);
}
}

View File

@ -8,13 +8,17 @@ import "../ownership/Ownable.sol";
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract Pausable is Ownable {
contract Pausable is Migratable, Ownable {
event Pause();
event Unpause();
bool public paused = false;
function initialize(address _sender) isInitializer("Pausable", "1.9.0") public {
Ownable.initialize(_sender);
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/

View File

@ -1,36 +0,0 @@
pragma solidity ^0.4.21;
import "../ownership/Ownable.sol";
import "../token/ERC20/ERC20Basic.sol";
/**
* @title TokenDestructible:
* @author Remco Bloemen <remco@2π.com>
* @dev Base contract that can be destroyed by owner. All funds in contract including
* listed tokens will be sent to the owner.
*/
contract TokenDestructible is Ownable {
function TokenDestructible() public payable { }
/**
* @notice Terminate contract and refund to owner
* @param tokens List of addresses of ERC20 or ERC20Basic token contracts to
refund.
* @notice The called token contracts could try to re-enter this contract. Only
supply token contracts you trust.
*/
function destroy(address[] tokens) onlyOwner public {
// Transfer tokens to owner
for (uint256 i = 0; i < tokens.length; i++) {
ERC20Basic token = ERC20Basic(tokens[i]);
uint256 balance = token.balanceOf(this);
token.transfer(owner, balance);
}
// Transfer Eth to owner and terminate contract
selfdestruct(owner);
}
}

View File

@ -1,21 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/ERC20.sol";
import "../crowdsale/emission/AllowanceCrowdsale.sol";
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
function AllowanceCrowdsaleImpl (
uint256 _rate,
address _wallet,
ERC20 _token,
address _tokenWallet
)
public
Crowdsale(_rate, _wallet, _token)
AllowanceCrowdsale(_tokenWallet)
{
}
}

View File

@ -4,6 +4,13 @@ import "../access/SignatureBouncer.sol";
contract SignatureBouncerMock is SignatureBouncer {
function initialize(address _sender)
isInitializer("SignatureBouncerMock", "1.9.0")
public
{
SignatureBouncer.initialize(_sender);
}
function checkValidSignature(address _address, bytes _sig)
public
view

View File

@ -1,21 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/ERC20.sol";
import "../crowdsale/validation/CappedCrowdsale.sol";
contract CappedCrowdsaleImpl is CappedCrowdsale {
function CappedCrowdsaleImpl (
uint256 _rate,
address _wallet,
ERC20 _token,
uint256 _cap
)
public
Crowdsale(_rate, _wallet, _token)
CappedCrowdsale(_cap)
{
}
}

View File

@ -1,25 +0,0 @@
pragma solidity ^0.4.21;
import "../../contracts/DayLimit.sol";
contract DayLimitMock is DayLimit {
uint256 public totalSpending;
function DayLimitMock(uint256 _value) public DayLimit(_value) {
totalSpending = 0;
}
function attemptSpend(uint256 _value) external limitedDaily(_value) {
totalSpending += _value;
}
function setDailyLimit(uint256 _newLimit) external {
_setDailyLimit(_newLimit);
}
function resetSpentToday() external {
_resetSpentToday();
}
}

View File

@ -5,5 +5,7 @@ import "../token/ERC20/DetailedERC20.sol";
contract DetailedERC20Mock is StandardToken, DetailedERC20 {
function DetailedERC20Mock(string _name, string _symbol, uint8 _decimals) DetailedERC20(_name, _symbol, _decimals) public {}
function DetailedERC20Mock(string _name, string _symbol, uint8 _decimals) public {
DetailedERC20.initialize(_name, _symbol, _decimals);
}
}

View File

@ -1,34 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/BasicToken.sol";
contract ERC223ContractInterface {
function tokenFallback(address _from, uint256 _value, bytes _data) external;
}
contract ERC223TokenMock is BasicToken {
function ERC223TokenMock(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply_ = initialBalance;
}
// ERC223 compatible transfer function (except the name)
function transferERC223(address _to, uint256 _value, bytes _data) public
returns (bool success)
{
transfer(_to, _value);
bool isContract = false;
// solium-disable-next-line security/no-inline-assembly
assembly {
isContract := not(iszero(extcodesize(_to)))
}
if (isContract) {
ERC223ContractInterface receiver = ERC223ContractInterface(_to);
receiver.tokenFallback(msg.sender, _value, _data);
}
return true;
}
}

View File

@ -9,9 +9,9 @@ import "../token/ERC721/ERC721Token.sol";
* and a public setter for metadata URI
*/
contract ERC721TokenMock is ERC721Token {
function ERC721TokenMock(string name, string symbol) public
ERC721Token(name, symbol)
{ }
function ERC721TokenMock(string name, string symbol) public {
ERC721Token.initialize(name, symbol);
}
function mint(address _to, uint256 _tokenId) public {
super._mint(_to, _tokenId);

View File

@ -1,15 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC827/ERC827Token.sol";
// mock class using ERC827 Token
contract ERC827TokenMock is ERC827Token {
function ERC827TokenMock(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply_ = initialBalance;
}
}

View File

@ -1,22 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/MintableToken.sol";
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
function FinalizableCrowdsaleImpl (
uint256 _openingTime,
uint256 _closingTime,
uint256 _rate,
address _wallet,
MintableToken _token
)
public
Crowdsale(_rate, _wallet, _token)
TimedCrowdsale(_openingTime, _closingTime)
{
}
}

View File

@ -1,16 +0,0 @@
pragma solidity ^0.4.21;
// @title Force Ether into a contract.
// @notice even
// if the contract is not payable.
// @notice To use, construct the contract with the target as argument.
// @author Remco Bloemen <remco@neufund.org>
contract ForceEther {
function ForceEther() public payable { }
function destroyAndSend(address _recipient) public {
selfdestruct(_recipient);
}
}

View File

@ -1,12 +0,0 @@
pragma solidity ^0.4.21;
import "../../contracts/ownership/HasNoEther.sol";
contract HasNoEtherTest is HasNoEther {
// Constructor with explicit payable — should still fail
function HasNoEtherTest() public payable {
}
}

View File

@ -1,24 +0,0 @@
pragma solidity ^0.4.21;
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
import "../math/SafeMath.sol";
contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
function IncreasingPriceCrowdsaleImpl (
uint256 _openingTime,
uint256 _closingTime,
address _wallet,
ERC20 _token,
uint256 _initialRate,
uint256 _finalRate
)
public
Crowdsale(_initialRate, _wallet, _token)
TimedCrowdsale(_openingTime, _closingTime)
IncreasingPriceCrowdsale(_initialRate, _finalRate)
{
}
}

View File

@ -1,19 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/ERC20.sol";
import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale {
function IndividuallyCappedCrowdsaleImpl (
uint256 _rate,
address _wallet,
ERC20 _token
)
public
Crowdsale(_rate, _wallet, _token)
{
}
}

View File

@ -1,17 +0,0 @@
pragma solidity ^0.4.21;
import {Bounty, Target} from "../../contracts/Bounty.sol";
contract InsecureTargetMock is Target {
function checkInvariant() public returns(bool) {
return false;
}
}
contract InsecureTargetBounty is Bounty {
function deployContract() internal returns (address) {
return new InsecureTargetMock();
}
}

View File

@ -1,13 +0,0 @@
pragma solidity ^0.4.21;
import "../LimitBalance.sol";
// mock class using LimitBalance
contract LimitBalanceMock is LimitBalance(1000) {
function limitedDeposit() public payable limitedPayable {
}
}

View File

@ -1,35 +0,0 @@
pragma solidity ^0.4.21;
contract MessageHelper {
event Show(bytes32 b32, uint256 number, string text);
event Buy(bytes32 b32, uint256 number, string text, uint256 value);
function showMessage( bytes32 message, uint256 number, string text ) public returns (bool) {
emit Show(message, number, text);
return true;
}
function buyMessage( bytes32 message, uint256 number, string text ) public payable returns (bool) {
emit Buy(
message,
number,
text,
msg.value);
return true;
}
function fail() public {
require(false);
}
function call(address to, bytes data) public returns (bool) {
// solium-disable-next-line security/no-low-level-calls
if (to.call(data))
return true;
else
return false;
}
}

View File

@ -1,19 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/MintableToken.sol";
import "../crowdsale/emission/MintedCrowdsale.sol";
contract MintedCrowdsaleImpl is MintedCrowdsale {
function MintedCrowdsaleImpl (
uint256 _rate,
address _wallet,
MintableToken _token
)
public
Crowdsale(_rate, _wallet, _token)
{
}
}

View File

@ -10,6 +10,8 @@ contract PausableMock is Pausable {
uint256 public count;
function PausableMock() public {
Ownable.initialize(msg.sender);
drasticMeasureTaken = false;
count = 0;
}

View File

@ -7,6 +7,8 @@ import "../token/ERC20/PausableToken.sol";
contract PausableTokenMock is PausableToken {
function PausableTokenMock(address initialAccount, uint initialBalance) public {
Ownable.initialize(msg.sender);
balances[initialAccount] = initialBalance;
}

View File

@ -1,22 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/ERC20.sol";
import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale {
function PostDeliveryCrowdsaleImpl (
uint256 _openingTime,
uint256 _closingTime,
uint256 _rate,
address _wallet,
ERC20 _token
)
public
TimedCrowdsale(_openingTime, _closingTime)
Crowdsale(_rate, _wallet, _token)
{
}
}

View File

@ -19,6 +19,8 @@ contract RBACMock is RBACWithAdmin {
function RBACMock(address[] _advisors)
public
{
RBACWithAdmin.initialize(msg.sender);
addRole(msg.sender, ROLE_ADVISOR);
for (uint256 i = 0; i < _advisors.length; i++) {

View File

@ -1,11 +0,0 @@
pragma solidity ^0.4.21;
contract ReentrancyAttack {
function callSender(bytes4 data) public {
// solium-disable-next-line security/no-low-level-calls
require(msg.sender.call(data));
}
}

View File

@ -1,46 +0,0 @@
pragma solidity ^0.4.21;
import "../ReentrancyGuard.sol";
import "./ReentrancyAttack.sol";
contract ReentrancyMock is ReentrancyGuard {
uint256 public counter;
function ReentrancyMock() public {
counter = 0;
}
function callback() external nonReentrant {
count();
}
function countLocalRecursive(uint256 n) public nonReentrant {
if (n > 0) {
count();
countLocalRecursive(n - 1);
}
}
function countThisRecursive(uint256 n) public nonReentrant {
bytes4 func = bytes4(keccak256("countThisRecursive(uint256)"));
if (n > 0) {
count();
// solium-disable-next-line security/no-low-level-calls
bool result = address(this).call(func, n - 1);
require(result == true);
}
}
function countAndCall(ReentrancyAttack attacker) public nonReentrant {
count();
bytes4 func = bytes4(keccak256("callback()"));
attacker.callSender(func);
}
function count() private {
counter += 1;
}
}

View File

@ -1,24 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/MintableToken.sol";
import "../crowdsale/distribution/RefundableCrowdsale.sol";
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
function RefundableCrowdsaleImpl (
uint256 _openingTime,
uint256 _closingTime,
uint256 _rate,
address _wallet,
MintableToken _token,
uint256 _goal
)
public
Crowdsale(_rate, _wallet, _token)
TimedCrowdsale(_openingTime, _closingTime)
RefundableCrowdsale(_goal)
{
}
}

View File

@ -21,11 +21,11 @@ contract ERC20FailingMock is ERC20 {
return false;
}
function balanceOf(address) public constant returns (uint256) {
function balanceOf(address) public view returns (uint256) {
return 0;
}
function allowance(address, address) public constant returns (uint256) {
function allowance(address, address) public view returns (uint256) {
return 0;
}
}
@ -48,11 +48,11 @@ contract ERC20SucceedingMock is ERC20 {
return true;
}
function balanceOf(address) public constant returns (uint256) {
function balanceOf(address) public view returns (uint256) {
return 0;
}
function allowance(address, address) public constant returns (uint256) {
function allowance(address, address) public view returns (uint256) {
return 0;
}
}

View File

@ -1,17 +0,0 @@
pragma solidity ^0.4.21;
import {Bounty, Target} from "../../contracts/Bounty.sol";
contract SecureTargetMock is Target {
function checkInvariant() public returns(bool) {
return true;
}
}
contract SecureTargetBounty is Bounty {
function deployContract() internal returns (address) {
return new SecureTargetMock();
}
}

View File

@ -1,22 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/ERC20.sol";
import "../crowdsale/validation/TimedCrowdsale.sol";
contract TimedCrowdsaleImpl is TimedCrowdsale {
function TimedCrowdsaleImpl (
uint256 _openingTime,
uint256 _closingTime,
uint256 _rate,
address _wallet,
ERC20 _token
)
public
Crowdsale(_rate, _wallet, _token)
TimedCrowdsale(_openingTime, _closingTime)
{
}
}

View File

@ -1,14 +0,0 @@
pragma solidity ^0.4.21;
import "../ownership/Whitelist.sol";
contract WhitelistMock is Whitelist {
function onlyWhitelistedCanDoThis()
onlyWhitelisted
view
external
{
}
}

View File

@ -1,19 +0,0 @@
pragma solidity ^0.4.21;
import "../token/ERC20/ERC20.sol";
import "../crowdsale/validation/WhitelistedCrowdsale.sol";
contract WhitelistedCrowdsaleImpl is WhitelistedCrowdsale {
function WhitelistedCrowdsaleImpl (
uint256 _rate,
address _wallet,
ERC20 _token
)
public
Crowdsale(_rate, _wallet, _token)
{
}
}

View File

@ -1,26 +0,0 @@
pragma solidity ^0.4.21;
import "./Ownable.sol";
import "../token/ERC20/ERC20Basic.sol";
import "../token/ERC20/SafeERC20.sol";
/**
* @title Contracts that should be able to recover tokens
* @author SylTi
* @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
* This will prevent any accidental loss of tokens.
*/
contract CanReclaimToken is Ownable {
using SafeERC20 for ERC20Basic;
/**
* @dev Reclaim all ERC20Basic compatible tokens
* @param token ERC20Basic The address of the token contract
*/
function reclaimToken(ERC20Basic token) external onlyOwner {
uint256 balance = token.balanceOf(this);
token.safeTransfer(owner, balance);
}
}

View File

@ -1,39 +0,0 @@
pragma solidity ^0.4.21;
import "./Ownable.sol";
/**
* @title Claimable
* @dev Extension for the Ownable contract, where the ownership needs to be claimed.
* This allows the new owner to accept the transfer.
*/
contract Claimable is Ownable {
address public pendingOwner;
/**
* @dev Modifier throws if called by any account other than the pendingOwner.
*/
modifier onlyPendingOwner() {
require(msg.sender == pendingOwner);
_;
}
/**
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner public {
pendingOwner = newOwner;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() onlyPendingOwner public {
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
pendingOwner = address(0);
}
}

View File

@ -1,22 +0,0 @@
pragma solidity ^0.4.21;
import "./Ownable.sol";
/**
* @title Contactable token
* @dev Basic version of a contactable contract, allowing the owner to provide a string with their
* contact information.
*/
contract Contactable is Ownable {
string public contactInformation;
/**
* @dev Allows the owner to set a string with their contact information.
* @param info The contact information to attach to the contract.
*/
function setContactInformation(string info) onlyOwner public {
contactInformation = info;
}
}

View File

@ -1,40 +0,0 @@
pragma solidity ^0.4.21;
import "./Claimable.sol";
/**
* @title DelayedClaimable
* @dev Extension for the Claimable contract, where the ownership needs to be claimed before/after
* a certain block number.
*/
contract DelayedClaimable is Claimable {
uint256 public end;
uint256 public start;
/**
* @dev Used to specify the time period during which a pending
* owner can claim ownership.
* @param _start The earliest time ownership can be claimed.
* @param _end The latest time ownership can be claimed.
*/
function setLimits(uint256 _start, uint256 _end) onlyOwner public {
require(_start <= _end);
end = _end;
start = _start;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within
* the specified start and end time.
*/
function claimOwnership() onlyPendingOwner public {
require((block.number <= end) && (block.number >= start));
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
pendingOwner = address(0);
end = 0;
}
}

View File

@ -1,22 +0,0 @@
pragma solidity ^0.4.21;
import "./Ownable.sol";
/**
* @title Contracts that should not own Contracts
* @author Remco Bloemen <remco@2π.com>
* @dev Should contracts (anything Ownable) end up being owned by this contract, it allows the owner
* of this contract to reclaim ownership of the contracts.
*/
contract HasNoContracts is Ownable {
/**
* @dev Reclaim ownership of Ownable contracts
* @param contractAddr The address of the Ownable to be reclaimed.
*/
function reclaimContract(address contractAddr) external onlyOwner {
Ownable contractInst = Ownable(contractAddr);
contractInst.transferOwnership(owner);
}
}

View File

@ -1,42 +0,0 @@
pragma solidity ^0.4.21;
import "./Ownable.sol";
/**
* @title Contracts that should not own Ether
* @author Remco Bloemen <remco@2π.com>
* @dev This tries to block incoming ether to prevent accidental loss of Ether. Should Ether end up
* in the contract, it will allow the owner to reclaim this ether.
* @notice Ether can still be sent to this contract by:
* calling functions labeled `payable`
* `selfdestruct(contract_address)`
* mining directly to the contract address
*/
contract HasNoEther is Ownable {
/**
* @dev Constructor that rejects incoming Ether
* @dev The `payable` flag is added so we can access `msg.value` without compiler warning. If we
* leave out payable, then Solidity will allow inheriting contracts to implement a payable
* constructor. By doing it this way we prevent a payable constructor from working. Alternatively
* we could use assembly to access msg.value.
*/
function HasNoEther() public payable {
require(msg.value == 0);
}
/**
* @dev Disallows direct send by settings a default function without the `payable` flag.
*/
function() external {
}
/**
* @dev Transfer all Ether held by the contract to the owner.
*/
function reclaimEther() external onlyOwner {
// solium-disable-next-line security/no-send
assert(owner.send(address(this).balance));
}
}

View File

@ -1,28 +0,0 @@
pragma solidity ^0.4.21;
import "./CanReclaimToken.sol";
/**
* @title Contracts that should not own Tokens
* @author Remco Bloemen <remco@2π.com>
* @dev This blocks incoming ERC223 tokens to prevent accidental loss of tokens.
* Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
* owner to reclaim the tokens.
*/
contract HasNoTokens is CanReclaimToken {
/**
* @dev Reject all ERC223 compatible tokens
* @param from_ address The address that is transferring the tokens
* @param value_ uint256 the amount of the specified token
* @param data_ Bytes The data passed from the caller.
*/
function tokenFallback(address from_, uint256 value_, bytes data_) external {
from_;
value_;
data_;
revert();
}
}

View File

@ -1,117 +0,0 @@
pragma solidity ^0.4.21;
import "./Ownable.sol";
/**
* @title Heritable
* @dev The Heritable contract provides ownership transfer capabilities, in the
* case that the current owner stops "heartbeating". Only the heir can pronounce the
* owner's death.
*/
contract Heritable is Ownable {
address private heir_;
// Time window the owner has to notify they are alive.
uint256 private heartbeatTimeout_;
// Timestamp of the owner's death, as pronounced by the heir.
uint256 private timeOfDeath_;
event HeirChanged(address indexed owner, address indexed newHeir);
event OwnerHeartbeated(address indexed owner);
event OwnerProclaimedDead(address indexed owner, address indexed heir, uint256 timeOfDeath);
event HeirOwnershipClaimed(address indexed previousOwner, address indexed newOwner);
/**
* @dev Throw an exception if called by any account other than the heir's.
*/
modifier onlyHeir() {
require(msg.sender == heir_);
_;
}
/**
* @notice Create a new Heritable Contract with heir address 0x0.
* @param _heartbeatTimeout time available for the owner to notify they are alive,
* before the heir can take ownership.
*/
function Heritable(uint256 _heartbeatTimeout) public {
setHeartbeatTimeout(_heartbeatTimeout);
}
function setHeir(address newHeir) public onlyOwner {
require(newHeir != owner);
heartbeat();
emit HeirChanged(owner, newHeir);
heir_ = newHeir;
}
/**
* @dev Use these getter functions to access the internal variables in
* an inherited contract.
*/
function heir() public view returns(address) {
return heir_;
}
function heartbeatTimeout() public view returns(uint256) {
return heartbeatTimeout_;
}
function timeOfDeath() public view returns(uint256) {
return timeOfDeath_;
}
/**
* @dev set heir = 0x0
*/
function removeHeir() public onlyOwner {
heartbeat();
heir_ = 0;
}
/**
* @dev Heir can pronounce the owners death. To claim the ownership, they will
* have to wait for `heartbeatTimeout` seconds.
*/
function proclaimDeath() public onlyHeir {
require(ownerLives());
emit OwnerProclaimedDead(owner, heir_, timeOfDeath_);
// solium-disable-next-line security/no-block-members
timeOfDeath_ = block.timestamp;
}
/**
* @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
*/
function heartbeat() public onlyOwner {
emit OwnerHeartbeated(owner);
timeOfDeath_ = 0;
}
/**
* @dev Allows heir to transfer ownership only if heartbeat has timed out.
*/
function claimHeirOwnership() public onlyHeir {
require(!ownerLives());
// solium-disable-next-line security/no-block-members
require(block.timestamp >= timeOfDeath_ + heartbeatTimeout_);
emit OwnershipTransferred(owner, heir_);
emit HeirOwnershipClaimed(owner, heir_);
owner = heir_;
timeOfDeath_ = 0;
}
function setHeartbeatTimeout(uint256 newHeartbeatTimeout) internal onlyOwner {
require(ownerLives());
heartbeatTimeout_ = newHeartbeatTimeout;
}
function ownerLives() internal view returns (bool) {
return timeOfDeath_ == 0;
}
}

View File

@ -1,15 +0,0 @@
pragma solidity ^0.4.21;
import "./HasNoEther.sol";
import "./HasNoTokens.sol";
import "./HasNoContracts.sol";
/**
* @title Base contract for contracts that should not own things.
* @author Remco Bloemen <remco@2π.com>
* @dev Solves a class of errors where a contract accidentally becomes owner of Ether, Tokens or
* Owned contracts. See respective base contracts for details.
*/
contract NoOwner is HasNoEther, HasNoTokens, HasNoContracts {
}

View File

@ -1,24 +1,25 @@
pragma solidity ^0.4.21;
import "zos-lib/contracts/migrations/Migratable.sol";
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
contract Ownable is Migratable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
function initialize(address _sender) public isInitializer("Ownable", "1.9.0") {
owner = _sender;
}
/**

View File

@ -1,81 +0,0 @@
pragma solidity ^0.4.21;
import "./Ownable.sol";
/**
* @title Whitelist
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
* @dev This simplifies the implementation of "user permissions".
*/
contract Whitelist is Ownable {
mapping(address => bool) public whitelist;
event WhitelistedAddressAdded(address addr);
event WhitelistedAddressRemoved(address addr);
/**
* @dev Throws if called by any account that's not whitelisted.
*/
modifier onlyWhitelisted() {
require(whitelist[msg.sender]);
_;
}
/**
* @dev add an address to the whitelist
* @param addr address
* @return true if the address was added to the whitelist, false if the address was already in the whitelist
*/
function addAddressToWhitelist(address addr) onlyOwner public returns(bool success) {
if (!whitelist[addr]) {
whitelist[addr] = true;
emit WhitelistedAddressAdded(addr);
success = true;
}
}
/**
* @dev add addresses to the whitelist
* @param addrs addresses
* @return true if at least one address was added to the whitelist,
* false if all addresses were already in the whitelist
*/
function addAddressesToWhitelist(address[] addrs) onlyOwner public returns(bool success) {
for (uint256 i = 0; i < addrs.length; i++) {
if (addAddressToWhitelist(addrs[i])) {
success = true;
}
}
}
/**
* @dev remove an address from the whitelist
* @param addr address
* @return true if the address was removed from the whitelist,
* false if the address wasn't in the whitelist in the first place
*/
function removeAddressFromWhitelist(address addr) onlyOwner public returns(bool success) {
if (whitelist[addr]) {
whitelist[addr] = false;
emit WhitelistedAddressRemoved(addr);
success = true;
}
}
/**
* @dev remove addresses from the whitelist
* @param addrs addresses
* @return true if at least one address was removed from the whitelist,
* false if all addresses weren't in the whitelist in the first place
*/
function removeAddressesFromWhitelist(address[] addrs) onlyOwner public returns(bool success) {
for (uint256 i = 0; i < addrs.length; i++) {
if (removeAddressFromWhitelist(addrs[i])) {
success = true;
}
}
}
}

View File

@ -1,6 +1,7 @@
pragma solidity ^0.4.21;
import "./RBAC.sol";
import "zos-lib/contracts/migrations/Migratable.sol";
/**
@ -9,7 +10,7 @@ import "./RBAC.sol";
* @dev It's recommended that you define constants in the contract,
* @dev like ROLE_ADMIN below, to avoid typos.
*/
contract RBACWithAdmin is RBAC {
contract RBACWithAdmin is RBAC, Migratable {
/**
* A constant role name for indicating admins.
*/
@ -26,12 +27,13 @@ contract RBACWithAdmin is RBAC {
}
/**
* @dev constructor. Sets msg.sender as admin by default
* @dev constructor. Sets initialAdmin as admin.
*/
function RBACWithAdmin()
function initialize(address initialAdmin)
isInitializer("RBACWithAdmin", "1.9.0")
public
{
addRole(msg.sender, ROLE_ADMIN);
addRole(initialAdmin, ROLE_ADMIN);
}
/**

View File

@ -1,6 +1,7 @@
pragma solidity ^0.4.21;
import "../math/SafeMath.sol";
import "zos-lib/contracts/migrations/Migratable.sol";
/**
@ -8,7 +9,7 @@ import "../math/SafeMath.sol";
* @dev Base contract that supports multiple payees claiming funds sent to this contract
* according to the proportion they own.
*/
contract SplitPayment {
contract SplitPayment is Migratable {
using SafeMath for uint256;
uint256 public totalShares = 0;
@ -21,7 +22,11 @@ contract SplitPayment {
/**
* @dev Constructor
*/
function SplitPayment(address[] _payees, uint256[] _shares) public payable {
function initialize(address[] _payees, uint256[] _shares)
isInitializer("SplitPayment", "1.9.0")
public
payable
{
require(_payees.length == _shares.length);
for (uint256 i = 0; i < _payees.length; i++) {

View File

@ -1,31 +0,0 @@
pragma solidity ^0.4.21;
import "./MintableToken.sol";
/**
* @title Capped token
* @dev Mintable token with a token cap.
*/
contract CappedToken is MintableToken {
uint256 public cap;
function CappedToken(uint256 _cap) public {
require(_cap > 0);
cap = _cap;
}
/**
* @dev Function to mint tokens
* @param _to The address that will receive the minted tokens.
* @param _amount The amount of tokens to mint.
* @return A boolean that indicates if the operation was successful.
*/
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
require(totalSupply_.add(_amount) <= cap);
return super.mint(_to, _amount);
}
}

View File

@ -1,14 +1,15 @@
pragma solidity ^0.4.21;
import "./ERC20.sol";
import "zos-lib/contracts/migrations/Migratable.sol";
contract DetailedERC20 is ERC20 {
contract DetailedERC20 is Migratable, ERC20 {
string public name;
string public symbol;
uint8 public decimals;
function DetailedERC20(string _name, string _symbol, uint8 _decimals) public {
function initialize(string _name, string _symbol, uint8 _decimals) public isInitializer("DetailedERC20", "1.9.0") {
name = _name;
symbol = _symbol;
decimals = _decimals;

View File

@ -0,0 +1,21 @@
pragma solidity ^0.4.21;
import "zos-lib/contracts/migrations/Migratable.sol";
import "./DetailedERC20.sol";
import "./MintableToken.sol";
contract DetailedMintableToken is Migratable, DetailedERC20, MintableToken {
function initialize(
address _sender,
string _name,
string _symbol,
uint8 _decimals
)
isInitializer("DetailedMintableToken", "1.9.0")
public
{
DetailedERC20.initialize(_name, _symbol, _decimals);
MintableToken.initialize(_sender);
}
}

View File

@ -0,0 +1,29 @@
pragma solidity ^0.4.21;
import "zos-lib/contracts/migrations/Migratable.sol";
import "./DetailedERC20.sol";
import "./MintableToken.sol";
contract DetailedPremintedToken is Migratable, DetailedERC20, StandardToken {
function initialize(
address _sender,
string _name,
string _symbol,
uint8 _decimals,
uint256 _initialBalance
)
isInitializer("DetailedPremintedToken", "1.9.0")
public
{
DetailedERC20.initialize(_name, _symbol, _decimals);
_premint(_sender, _initialBalance);
}
function _premint(address _to, uint256 _value) internal {
totalSupply_ += _value;
balances[_to] += _value;
emit Transfer(0, _to, _value);
}
}

View File

@ -2,6 +2,7 @@ pragma solidity ^0.4.21;
import "./StandardToken.sol";
import "../../ownership/Ownable.sol";
import "zos-lib/contracts/migrations/Migratable.sol";
/**
@ -10,7 +11,7 @@ import "../../ownership/Ownable.sol";
* @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/120
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
*/
contract MintableToken is StandardToken, Ownable {
contract MintableToken is Migratable, Ownable, StandardToken {
event Mint(address indexed to, uint256 amount);
event MintFinished();
@ -22,6 +23,10 @@ contract MintableToken is StandardToken, Ownable {
_;
}
function initialize(address _sender) isInitializer("MintableToken", "1.9.0") public {
Ownable.initialize(_sender);
}
/**
* @dev Function to mint tokens
* @param _to The address that will receive the minted tokens.

View File

@ -8,7 +8,11 @@ import "../../lifecycle/Pausable.sol";
* @title Pausable token
* @dev StandardToken modified with pausable transfers.
**/
contract PausableToken is StandardToken, Pausable {
contract PausableToken is Migratable, StandardToken, Pausable {
function initialize(address _sender) isInitializer("PausableToken", "1.9.0") public {
Pausable.initialize(_sender);
}
function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) {
return super.transfer(_to, _value);

View File

@ -3,6 +3,7 @@ pragma solidity ^0.4.18;
import "./BurnableToken.sol";
import "./StandardToken.sol";
/**
* @title Standard Burnable Token
* @dev Adds burnFrom method to ERC20 implementations

View File

@ -1,6 +1,7 @@
pragma solidity ^0.4.21;
import "./SafeERC20.sol";
import "zos-lib/contracts/migrations/Migratable.sol";
/**
@ -8,7 +9,7 @@ import "./SafeERC20.sol";
* @dev TokenTimelock is a token holder contract that will allow a
* beneficiary to extract the tokens after a given release time
*/
contract TokenTimelock {
contract TokenTimelock is Migratable {
using SafeERC20 for ERC20Basic;
// ERC20 basic token contract being held
@ -20,7 +21,15 @@ contract TokenTimelock {
// timestamp when token release is enabled
uint256 public releaseTime;
function TokenTimelock(ERC20Basic _token, address _beneficiary, uint256 _releaseTime) public {
function initialize(
address _sender,
ERC20Basic _token,
address _beneficiary,
uint256 _releaseTime
)
isInitializer("TokenTimelock", "1.9.0")
public
{
// solium-disable-next-line security/no-block-members
require(_releaseTime > block.timestamp);
token = _token;

View File

@ -6,6 +6,7 @@ import "./ERC20Basic.sol";
import "./SafeERC20.sol";
import "../../ownership/Ownable.sol";
import "../../math/SafeMath.sol";
import "zos-lib/contracts/migrations/Migratable.sol";
/**
@ -14,7 +15,7 @@ import "../../math/SafeMath.sol";
* typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
* owner.
*/
contract TokenVesting is Ownable {
contract TokenVesting is Migratable, Ownable {
using SafeMath for uint256;
using SafeERC20 for ERC20Basic;
@ -42,7 +43,8 @@ contract TokenVesting is Ownable {
* @param _duration duration in seconds of the period in which the tokens will vest
* @param _revocable whether the vesting is revocable or not
*/
function TokenVesting(
function initialize(
address _sender,
address _beneficiary,
uint256 _start,
uint256 _cliff,
@ -50,7 +52,10 @@ contract TokenVesting is Ownable {
bool _revocable
)
public
isInitializer("TokenVesting", "1.9.0")
{
Ownable.initialize(_sender);
require(_beneficiary != address(0));
require(_cliff <= _duration);

View File

@ -1,15 +0,0 @@
pragma solidity ^0.4.21;
import "./ERC721.sol";
/**
* @title ERC-721 methods shipped in OpenZeppelin v1.7.0, removed in the latest version of the standard
* @dev Only use this interface for compatibility with previously deployed contracts
* @dev Use ERC721 for interacting with new contracts which are standard-compliant
*/
contract DeprecatedERC721 is ERC721 {
function takeOwnership(uint256 _tokenId) public;
function transfer(address _to, uint256 _tokenId) public;
function tokensOf(address _owner) public view returns (uint256[]);
}

View File

@ -2,6 +2,7 @@ pragma solidity ^0.4.21;
import "./ERC721.sol";
import "./ERC721BasicToken.sol";
import "zos-lib/contracts/migrations/Migratable.sol";
/**
@ -10,7 +11,7 @@ import "./ERC721BasicToken.sol";
* Moreover, it includes approve all functionality using operator terminology
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
*/
contract ERC721Token is ERC721, ERC721BasicToken {
contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
// Token name
string internal name_;
@ -35,7 +36,7 @@ contract ERC721Token is ERC721, ERC721BasicToken {
/**
* @dev Constructor function
*/
function ERC721Token(string _name, string _symbol) public {
function initialize(string _name, string _symbol) public isInitializer("ERC721Token", "1.9.0") {
name_ = _name;
symbol_ = _symbol;
}

View File

@ -0,0 +1,19 @@
pragma solidity ^0.4.21;
import "./ERC721Token.sol";
import "../../ownership/Ownable.sol";
/**
* @title Mintable ERC721 Token
*/
contract MintableERC721Token is Migratable, Ownable, ERC721Token {
function initialize(address _sender, string _name, string _symbol) isInitializer("MintableERC721Token", "1.9.0") public {
Ownable.initialize(_sender);
ERC721Token.initialize(_name, _symbol);
}
function mint(address _to, uint256 _tokenId) onlyOwner public {
_mint(_to, _tokenId);
}
}

View File

@ -1,26 +0,0 @@
pragma solidity ^0.4.21;
import "../ERC20/ERC20.sol";
/**
* @title ERC827 interface, an extension of ERC20 token standard
*
* @dev Interface of a ERC827 token, following the ERC20 standard with extra
* @dev methods to transfer value and data and execute calls in transfers and
* @dev approvals.
*/
contract ERC827 is ERC20 {
function approveAndCall( address _spender, uint256 _value, bytes _data) public payable returns (bool);
function transferAndCall( address _to, uint256 _value, bytes _data) public payable returns (bool);
function transferFromAndCall(
address _from,
address _to,
uint256 _value,
bytes _data
)
public
payable
returns (bool);
}

View File

@ -1,144 +0,0 @@
/* solium-disable security/no-low-level-calls */
pragma solidity ^0.4.21;
import "./ERC827.sol";
import "../ERC20/StandardToken.sol";
/**
* @title ERC827, an extension of ERC20 token standard
*
* @dev Implementation the ERC827, following the ERC20 standard with extra
* @dev methods to transfer value and data and execute calls in transfers and
* @dev approvals.
*
* @dev Uses OpenZeppelin StandardToken.
*/
contract ERC827Token is ERC827, StandardToken {
/**
* @dev Addition to ERC20 token methods. It allows to
* @dev approve the transfer of value and execute a call with the sent data.
*
* @dev Beware that changing an allowance with this method brings the risk that
* @dev someone may use both the old and the new allowance by unfortunate
* @dev transaction ordering. One possible solution to mitigate this race condition
* @dev is to first reduce the spender's allowance to 0 and set the desired value
* @dev afterwards:
* @dev https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* @param _spender The address that will spend the funds.
* @param _value The amount of tokens to be spent.
* @param _data ABI-encoded contract call to call `_to` address.
*
* @return true if the call function was executed successfully
*/
function approveAndCall(address _spender, uint256 _value, bytes _data) public payable returns (bool) {
require(_spender != address(this));
super.approve(_spender, _value);
// solium-disable-next-line security/no-call-value
require(_spender.call.value(msg.value)(_data));
return true;
}
/**
* @dev Addition to ERC20 token methods. Transfer tokens to a specified
* @dev address and execute a call with the sent data on the same transaction
*
* @param _to address The address which you want to transfer to
* @param _value uint256 the amout of tokens to be transfered
* @param _data ABI-encoded contract call to call `_to` address.
*
* @return true if the call function was executed successfully
*/
function transferAndCall(address _to, uint256 _value, bytes _data) public payable returns (bool) {
require(_to != address(this));
super.transfer(_to, _value);
// solium-disable-next-line security/no-call-value
require(_to.call.value(msg.value)(_data));
return true;
}
/**
* @dev Addition to ERC20 token methods. Transfer tokens from one address to
* @dev another and make a contract call on the same transaction
*
* @param _from The address which you want to send tokens from
* @param _to The address which you want to transfer to
* @param _value The amout of tokens to be transferred
* @param _data ABI-encoded contract call to call `_to` address.
*
* @return true if the call function was executed successfully
*/
function transferFromAndCall(
address _from,
address _to,
uint256 _value,
bytes _data
)
public payable returns (bool)
{
require(_to != address(this));
super.transferFrom(_from, _to, _value);
// solium-disable-next-line security/no-call-value
require(_to.call.value(msg.value)(_data));
return true;
}
/**
* @dev Addition to StandardToken methods. Increase the amount of tokens that
* @dev an owner allowed to a spender and execute a call with the sent data.
*
* @dev approve should be called when allowed[_spender] == 0. To increment
* @dev allowed value is better to use this function to avoid 2 calls (and wait until
* @dev the first transaction is mined)
* @dev From MonolithDAO Token.sol
*
* @param _spender The address which will spend the funds.
* @param _addedValue The amount of tokens to increase the allowance by.
* @param _data ABI-encoded contract call to call `_spender` address.
*/
function increaseApprovalAndCall(address _spender, uint _addedValue, bytes _data) public payable returns (bool) {
require(_spender != address(this));
super.increaseApproval(_spender, _addedValue);
// solium-disable-next-line security/no-call-value
require(_spender.call.value(msg.value)(_data));
return true;
}
/**
* @dev Addition to StandardToken methods. Decrease the amount of tokens that
* @dev an owner allowed to a spender and execute a call with the sent data.
*
* @dev approve should be called when allowed[_spender] == 0. To decrement
* @dev allowed value is better to use this function to avoid 2 calls (and wait until
* @dev the first transaction is mined)
* @dev From MonolithDAO Token.sol
*
* @param _spender The address which will spend the funds.
* @param _subtractedValue The amount of tokens to decrease the allowance by.
* @param _data ABI-encoded contract call to call `_spender` address.
*/
function decreaseApprovalAndCall(address _spender, uint _subtractedValue, bytes _data) public payable returns (bool) {
require(_spender != address(this));
super.decreaseApproval(_spender, _subtractedValue);
// solium-disable-next-line security/no-call-value
require(_spender.call.value(msg.value)(_data));
return true;
}
}

View File

@ -1,6 +1,6 @@
{
"package_name": "zeppelin",
"version": "1.9.0",
"version": "1.9.1",
"description": "Secure Smart Contract library for Solidity",
"authors": [
"Manuel Araoz <manuelaraoz@gmail.com>"

7673
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,16 @@
{
"name": "openzeppelin-solidity",
"version": "1.9.0",
"name": "openzeppelin-zos",
"version": "1.9.1",
"description": "Secure Smart Contract library for Solidity",
"files": [
"contracts",
"test"
"build",
"test",
"zos.json",
"zos.*.json"
],
"scripts": {
"prepack": "truffle compile",
"test": "scripts/test.sh",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
@ -59,6 +63,13 @@
"solidity-coverage": "^0.4.15",
"solium": "^1.1.6",
"truffle": "^4.1.5",
"truffle-hdwallet-provider": "0.0.3"
"truffle-hdwallet-provider": "0.0.3",
"zos": "^0.8.0"
},
"dependencies": {
"zos-lib": "^0.1.26"
},
"peerDependencies": {
"zos-lib": "^0.1.26"
}
}

View File

@ -1,111 +0,0 @@
let sendReward = function (sender, receiver, value) {
web3.eth.sendTransaction({
from: sender,
to: receiver,
value: value,
});
};
var SecureTargetBounty = artifacts.require('SecureTargetBounty');
var InsecureTargetBounty = artifacts.require('InsecureTargetBounty');
function awaitEvent (event, handler) {
return new Promise((resolve, reject) => {
function wrappedHandler (...args) {
Promise.resolve(handler(...args)).then(resolve).catch(reject);
}
event.watch(wrappedHandler);
});
}
contract('Bounty', function (accounts) {
it('sets reward', async function () {
let owner = accounts[0];
let reward = web3.toWei(1, 'ether');
let bounty = await SecureTargetBounty.new();
sendReward(owner, bounty.address, reward);
assert.equal(reward, web3.eth.getBalance(bounty.address).toNumber());
});
it('empties itself when destroyed', async function () {
let owner = accounts[0];
let reward = web3.toWei(1, 'ether');
let bounty = await SecureTargetBounty.new();
sendReward(owner, bounty.address, reward);
assert.equal(reward, web3.eth.getBalance(bounty.address).toNumber());
await bounty.destroy();
assert.equal(0, web3.eth.getBalance(bounty.address).toNumber());
});
describe('Against secure contract', function () {
it('cannot claim reward', async function () {
let owner = accounts[0];
let researcher = accounts[1];
let reward = web3.toWei(1, 'ether');
let bounty = await SecureTargetBounty.new();
let event = bounty.TargetCreated({});
let watcher = async function (err, result) {
event.stopWatching();
if (err) { throw err; }
var targetAddress = result.args.createdAddress;
sendReward(owner, bounty.address, reward);
assert.equal(reward,
web3.eth.getBalance(bounty.address).toNumber());
try {
await bounty.claim(targetAddress, { from: researcher });
assert.isTrue(false); // should never reach here
} catch (error) {
let reClaimedBounty = await bounty.claimed.call();
assert.isFalse(reClaimedBounty);
}
try {
await bounty.withdrawPayments({ from: researcher });
assert.isTrue(false); // should never reach here
} catch (err) {
assert.equal(reward,
web3.eth.getBalance(bounty.address).toNumber());
}
};
await bounty.createTarget({ from: researcher });
await awaitEvent(event, watcher);
});
});
describe('Against broken contract', function () {
it('claims reward', async function () {
let owner = accounts[0];
let researcher = accounts[1];
let reward = web3.toWei(1, 'ether');
let bounty = await InsecureTargetBounty.new();
let event = bounty.TargetCreated({});
let watcher = async function (err, result) {
event.stopWatching();
if (err) { throw err; }
let targetAddress = result.args.createdAddress;
sendReward(owner, bounty.address, reward);
assert.equal(reward, web3.eth.getBalance(bounty.address).toNumber());
await bounty.claim(targetAddress, { from: researcher });
let claim = await bounty.claimed.call();
assert.isTrue(claim);
await bounty.withdrawPayments({ from: researcher });
assert.equal(0, web3.eth.getBalance(bounty.address).toNumber());
};
await bounty.createTarget({ from: researcher });
await awaitEvent(event, watcher);
});
});
});

View File

@ -1,88 +0,0 @@
import latestTime from './helpers/latestTime';
import { increaseTimeTo, duration } from './helpers/increaseTime';
import assertRevert from './helpers/assertRevert';
const DayLimitMock = artifacts.require('DayLimitMock');
contract('DayLimit', function (accounts) {
let dayLimit;
let initLimit = 10;
beforeEach(async function () {
this.startTime = latestTime();
dayLimit = await DayLimitMock.new(initLimit);
});
it('should construct with the passed daily limit', async function () {
let dailyLimit = await dayLimit.dailyLimit();
assert.equal(initLimit, dailyLimit);
});
it('should be able to spend if daily limit is not reached', async function () {
await dayLimit.attemptSpend(8);
let spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await dayLimit.attemptSpend(2);
spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 10);
});
it('should prevent spending if daily limit is reached', async function () {
await dayLimit.attemptSpend(8);
let spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await assertRevert(dayLimit.attemptSpend(3));
});
it('should allow spending if daily limit is reached and then set higher', async function () {
await dayLimit.attemptSpend(8);
let spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await assertRevert(dayLimit.attemptSpend(3));
spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await dayLimit.setDailyLimit(15);
await dayLimit.attemptSpend(3);
spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 11);
});
it('should allow spending if daily limit is reached and then amount spent is reset', async function () {
await dayLimit.attemptSpend(8);
let spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await assertRevert(dayLimit.attemptSpend(3));
spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await dayLimit.resetSpentToday();
await dayLimit.attemptSpend(3);
spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 3);
});
it('should allow spending if daily limit is reached and then the next has come', async function () {
let limit = 10;
let dayLimit = await DayLimitMock.new(limit);
await dayLimit.attemptSpend(8);
let spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await assertRevert(dayLimit.attemptSpend(3));
spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 8);
await increaseTimeTo(this.startTime + duration.days(1));
await dayLimit.attemptSpend(3);
spentToday = await dayLimit.spentToday();
assert.equal(spentToday, 3);
});
});

View File

@ -1,136 +0,0 @@
import increaseTime from './helpers/increaseTime';
import expectThrow from './helpers/expectThrow';
import assertRevert from './helpers/assertRevert';
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
const Heritable = artifacts.require('Heritable');
contract('Heritable', function (accounts) {
let heritable;
let owner;
beforeEach(async function () {
heritable = await Heritable.new(4141);
owner = await heritable.owner();
});
it('should start off with an owner, but without heir', async function () {
const heir = await heritable.heir();
assert.equal(typeof (owner), 'string');
assert.equal(typeof (heir), 'string');
assert.notStrictEqual(
owner, NULL_ADDRESS,
'Owner shouldn\'t be the null address'
);
assert.isTrue(
heir === NULL_ADDRESS,
'Heir should be the null address'
);
});
it('only owner should set heir', async function () {
const newHeir = accounts[1];
const someRandomAddress = accounts[2];
assert.isTrue(owner !== someRandomAddress);
await heritable.setHeir(newHeir, { from: owner });
await expectThrow(heritable.setHeir(newHeir, { from: someRandomAddress }));
});
it('owner can\'t be heir', async function () {
await assertRevert(heritable.setHeir(owner, { from: owner }));
});
it('owner can remove heir', async function () {
const newHeir = accounts[1];
await heritable.setHeir(newHeir, { from: owner });
let heir = await heritable.heir();
assert.notStrictEqual(heir, NULL_ADDRESS);
await heritable.removeHeir();
heir = await heritable.heir();
assert.isTrue(heir === NULL_ADDRESS);
});
it('heir can claim ownership only if owner is dead and timeout was reached', async function () {
const heir = accounts[1];
await heritable.setHeir(heir, { from: owner });
await expectThrow(heritable.claimHeirOwnership({ from: heir }));
await heritable.proclaimDeath({ from: heir });
await increaseTime(1);
await expectThrow(heritable.claimHeirOwnership({ from: heir }));
await increaseTime(4141);
await heritable.claimHeirOwnership({ from: heir });
assert.isTrue(await heritable.heir() === heir);
});
it('only heir can proclaim death', async function () {
const someRandomAddress = accounts[2];
await assertRevert(heritable.proclaimDeath({ from: owner }));
await assertRevert(heritable.proclaimDeath({ from: someRandomAddress }));
});
it('heir can\'t proclaim death if owner is death', async function () {
const heir = accounts[1];
await heritable.setHeir(heir, { from: owner });
await heritable.proclaimDeath({ from: heir });
await assertRevert(heritable.proclaimDeath({ from: heir }));
});
it('heir can\'t claim ownership if owner heartbeats', async function () {
const heir = accounts[1];
await heritable.setHeir(heir, { from: owner });
await heritable.proclaimDeath({ from: heir });
await heritable.heartbeat({ from: owner });
await expectThrow(heritable.claimHeirOwnership({ from: heir }));
await heritable.proclaimDeath({ from: heir });
await increaseTime(4141);
await heritable.heartbeat({ from: owner });
await expectThrow(heritable.claimHeirOwnership({ from: heir }));
});
it('should log events appropriately', async function () {
const heir = accounts[1];
const setHeirLogs = (await heritable.setHeir(heir, { from: owner })).logs;
const setHeirEvent = setHeirLogs.find(e => e.event === 'HeirChanged');
assert.isTrue(setHeirEvent.args.owner === owner);
assert.isTrue(setHeirEvent.args.newHeir === heir);
const heartbeatLogs = (await heritable.heartbeat({ from: owner })).logs;
const heartbeatEvent = heartbeatLogs.find(e => e.event === 'OwnerHeartbeated');
assert.isTrue(heartbeatEvent.args.owner === owner);
const proclaimDeathLogs = (await heritable.proclaimDeath({ from: heir })).logs;
const ownerDeadEvent = proclaimDeathLogs.find(e => e.event === 'OwnerProclaimedDead');
assert.isTrue(ownerDeadEvent.args.owner === owner);
assert.isTrue(ownerDeadEvent.args.heir === heir);
await increaseTime(4141);
const claimHeirOwnershipLogs = (await heritable.claimHeirOwnership({ from: heir })).logs;
const ownershipTransferredEvent = claimHeirOwnershipLogs.find(e => e.event === 'OwnershipTransferred');
const heirOwnershipClaimedEvent = claimHeirOwnershipLogs.find(e => e.event === 'HeirOwnershipClaimed');
assert.isTrue(ownershipTransferredEvent.args.previousOwner === owner);
assert.isTrue(ownershipTransferredEvent.args.newOwner === heir);
assert.isTrue(heirOwnershipClaimedEvent.args.previousOwner === owner);
assert.isTrue(heirOwnershipClaimedEvent.args.newOwner === heir);
});
it('timeOfDeath can be queried', async function () {
assert.equal(await heritable.timeOfDeath(), 0);
});
it('heartbeatTimeout can be queried', async function () {
assert.equal(await heritable.heartbeatTimeout(), 4141);
});
});

View File

@ -1,47 +0,0 @@
import assertRevert from './helpers/assertRevert';
var LimitBalanceMock = artifacts.require('LimitBalanceMock');
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;
await assertRevert(lb.limitedDeposit({ value: amount }));
});
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);
await assertRevert(lb.limitedDeposit({ value: amount + 1 }));
});
});

View File

@ -1,31 +0,0 @@
import expectThrow from './helpers/expectThrow';
const ReentrancyMock = artifacts.require('ReentrancyMock');
const ReentrancyAttack = artifacts.require('ReentrancyAttack');
contract('ReentrancyGuard', function (accounts) {
let reentrancyMock;
beforeEach(async function () {
reentrancyMock = await ReentrancyMock.new();
let initialCounter = await reentrancyMock.counter();
assert.equal(initialCounter, 0);
});
it('should not allow remote callback', async function () {
let attacker = await ReentrancyAttack.new();
await expectThrow(reentrancyMock.countAndCall(attacker.address));
});
// The following are more side-effects than intended behaviour:
// I put them here as documentation, and to monitor any changes
// in the side-effects.
it('should not allow local recursion', async function () {
await expectThrow(reentrancyMock.countLocalRecursive(10));
});
it('should not allow indirect local recursion', async function () {
await expectThrow(reentrancyMock.countThisRecursive(10));
});
});

View File

@ -1,33 +0,0 @@
import expectThrow from './helpers/expectThrow';
const SimpleSavingsWallet = artifacts.require('SimpleSavingsWallet');
contract('SimpleSavingsWallet', function (accounts) {
let savingsWallet;
let owner;
const paymentAmount = 4242;
beforeEach(async function () {
savingsWallet = await SimpleSavingsWallet.new(4141);
owner = await savingsWallet.owner();
});
it('should receive funds', async function () {
await web3.eth.sendTransaction({ from: owner, to: savingsWallet.address, value: paymentAmount });
assert.isTrue((new web3.BigNumber(paymentAmount)).equals(web3.eth.getBalance(savingsWallet.address)));
});
it('owner can send funds', async function () {
// Receive payment so we have some money to spend.
await web3.eth.sendTransaction({ from: accounts[9], to: savingsWallet.address, value: 1000000 });
await expectThrow(savingsWallet.sendTo(0, paymentAmount, { from: owner }));
await expectThrow(savingsWallet.sendTo(savingsWallet.address, paymentAmount, { from: owner }));
await expectThrow(savingsWallet.sendTo(accounts[1], 0, { from: owner }));
const balance = web3.eth.getBalance(accounts[1]);
await savingsWallet.sendTo(accounts[1], paymentAmount, { from: owner });
assert.isTrue(balance.plus(paymentAmount).equals(web3.eth.getBalance(accounts[1])));
});
});

View File

@ -17,7 +17,8 @@ export const getSigner = (contract, signer, data = '') => (addr) => {
contract('Bouncer', ([_, owner, authorizedUser, anyone, bouncerAddress, newBouncer]) => {
before(async function () {
this.bouncer = await Bouncer.new({ from: owner });
this.bouncer = await Bouncer.new();
await this.bouncer.initialize(owner);
this.roleBouncer = await this.bouncer.ROLE_BOUNCER();
this.genSig = getSigner(this.bouncer, bouncerAddress);
});

View File

@ -1,77 +0,0 @@
import ether from '../helpers/ether';
import assertRevert from '../helpers/assertRevert';
const BigNumber = web3.BigNumber;
const should = require('chai')
.use(require('chai-as-promised'))
.use(require('chai-bignumber')(BigNumber))
.should();
const AllowanceCrowdsale = artifacts.require('AllowanceCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');
contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenWallet]) {
const rate = new BigNumber(1);
const value = ether(0.42);
const expectedTokenAmount = rate.mul(value);
const tokenAllowance = new BigNumber('1e22');
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
beforeEach(async function () {
this.token = await SimpleToken.new({ from: tokenWallet });
this.crowdsale = await AllowanceCrowdsale.new(rate, wallet, this.token.address, tokenWallet);
await this.token.approve(this.crowdsale.address, tokenAllowance, { from: tokenWallet });
});
describe('accepting payments', function () {
it('should accept sends', async function () {
await this.crowdsale.send(value).should.be.fulfilled;
});
it('should accept payments', async function () {
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }).should.be.fulfilled;
});
});
describe('high-level purchase', function () {
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 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('check remaining allowance', function () {
it('should report correct allowace left', async function () {
let remainingAllowance = tokenAllowance - expectedTokenAmount;
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser });
let tokensRemaining = await this.crowdsale.remainingTokens();
tokensRemaining.should.be.bignumber.equal(remainingAllowance);
});
});
describe('when token wallet is different from token address', function () {
it('creation reverts', async function () {
this.token = await SimpleToken.new({ from: tokenWallet });
await assertRevert(AllowanceCrowdsale.new(rate, wallet, this.token.address, ZERO_ADDRESS));
});
});
});

View File

@ -1,69 +0,0 @@
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 CappedCrowdsale = artifacts.require('CappedCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');
contract('CappedCrowdsale', function ([_, wallet]) {
const rate = new BigNumber(1);
const cap = ether(100);
const lessThanCap = ether(60);
const tokenSupply = new BigNumber('1e22');
beforeEach(async function () {
this.token = await SimpleToken.new();
this.crowdsale = await CappedCrowdsale.new(rate, wallet, this.token.address, cap);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
describe('creating a valid crowdsale', function () {
it('should fail with zero cap', async function () {
await CappedCrowdsale.new(rate, wallet, 0, this.token.address).should.be.rejectedWith(EVMRevert);
});
});
describe('accepting payments', function () {
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 () {
it('should not reach cap if sent under cap', async function () {
let capReached = await this.crowdsale.capReached();
capReached.should.equal(false);
await this.crowdsale.send(lessThanCap);
capReached = await this.crowdsale.capReached();
capReached.should.equal(false);
});
it('should not reach cap if sent just under cap', async function () {
await this.crowdsale.send(cap.minus(1));
let capReached = await this.crowdsale.capReached();
capReached.should.equal(false);
});
it('should reach cap if cap sent', async function () {
await this.crowdsale.send(cap);
let capReached = await this.crowdsale.capReached();
capReached.should.equal(true);
});
});
});

View File

@ -1,81 +0,0 @@
import ether from '../helpers/ether';
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 SimpleToken = artifacts.require('SimpleToken');
contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
const rate = new BigNumber(1);
const value = ether(42);
const tokenSupply = new BigNumber('1e22');
const expectedTokenAmount = rate.mul(value);
beforeEach(async function () {
this.token = await SimpleToken.new();
this.crowdsale = await Crowdsale.new(rate, wallet, this.token.address);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
describe('accepting payments', function () {
it('should accept payments', async function () {
await this.crowdsale.send(value).should.be.fulfilled;
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }).should.be.fulfilled;
});
});
describe('high-level purchase', function () {
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 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 () {
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 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);
});
});
});

View File

@ -1,62 +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('FinalizableCrowdsaleImpl');
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 ganache
await advanceBlock();
});
beforeEach(async function () {
this.openingTime = latestTime() + duration.weeks(1);
this.closingTime = this.openingTime + duration.weeks(1);
this.afterClosingTime = this.closingTime + duration.seconds(1);
this.token = await MintableToken.new();
this.crowdsale = await FinalizableCrowdsale.new(
this.openingTime, this.closingTime, rate, wallet, this.token.address, { from: owner }
);
await this.token.transferOwnership(this.crowdsale.address);
});
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.afterClosingTime);
await this.crowdsale.finalize({ from: thirdparty }).should.be.rejectedWith(EVMRevert);
});
it('can be finalized by owner after ending', async function () {
await increaseTimeTo(this.afterClosingTime);
await this.crowdsale.finalize({ from: owner }).should.be.fulfilled;
});
it('cannot be finalized twice', async function () {
await increaseTimeTo(this.afterClosingTime);
await this.crowdsale.finalize({ from: owner });
await this.crowdsale.finalize({ from: owner }).should.be.rejectedWith(EVMRevert);
});
it('logs finalized', async function () {
await increaseTimeTo(this.afterClosingTime);
const { logs } = await this.crowdsale.finalize({ from: owner });
const event = logs.find(e => e.event === 'Finalized');
should.exist(event);
});
});

View File

@ -1,92 +0,0 @@
import ether from '../helpers/ether';
import { advanceBlock } from '../helpers/advanceToBlock';
import { increaseTimeTo, duration } from '../helpers/increaseTime';
import latestTime from '../helpers/latestTime';
const BigNumber = web3.BigNumber;
require('chai')
.use(require('chai-as-promised'))
.use(require('chai-bignumber')(BigNumber))
.should();
const IncreasingPriceCrowdsale = artifacts.require('IncreasingPriceCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');
contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser]) {
const value = ether(1);
const tokenSupply = new BigNumber('1e22');
describe('rate during crowdsale should change at a fixed step every block', async function () {
let balance;
const initialRate = new BigNumber(9166);
const finalRate = new BigNumber(5500);
const rateAtTime150 = new BigNumber(9166);
const rateAtTime300 = new BigNumber(9165);
const rateAtTime1500 = new BigNumber(9157);
const rateAtTime30 = new BigNumber(9166);
const rateAtTime150000 = new BigNumber(8257);
const rateAtTime450000 = new BigNumber(6439);
beforeEach(async function () {
await advanceBlock();
this.startTime = latestTime() + duration.weeks(1);
this.closingTime = this.startTime + duration.weeks(1);
this.afterClosingTime = this.closingTime + duration.seconds(1);
this.token = await SimpleToken.new();
this.crowdsale = await IncreasingPriceCrowdsale.new(
this.startTime, this.closingTime, wallet, this.token.address, initialRate, finalRate
);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
it('at start', async function () {
await increaseTimeTo(this.startTime);
await this.crowdsale.buyTokens(investor, { value, from: purchaser });
balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value.mul(initialRate));
});
it('at time 150', async function () {
await increaseTimeTo(this.startTime + 150);
await this.crowdsale.buyTokens(investor, { value, from: purchaser });
balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value.mul(rateAtTime150));
});
it('at time 300', async function () {
await increaseTimeTo(this.startTime + 300);
await this.crowdsale.buyTokens(investor, { value, from: purchaser });
balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value.mul(rateAtTime300));
});
it('at time 1500', async function () {
await increaseTimeTo(this.startTime + 1500);
await this.crowdsale.buyTokens(investor, { value, from: purchaser });
balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value.mul(rateAtTime1500));
});
it('at time 30', async function () {
await increaseTimeTo(this.startTime + 30);
await this.crowdsale.buyTokens(investor, { value, from: purchaser });
balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value.mul(rateAtTime30));
});
it('at time 150000', async function () {
await increaseTimeTo(this.startTime + 150000);
await this.crowdsale.buyTokens(investor, { value, from: purchaser });
balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value.mul(rateAtTime150000));
});
it('at time 450000', async function () {
await increaseTimeTo(this.startTime + 450000);
await this.crowdsale.buyTokens(investor, { value, from: purchaser });
balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value.mul(rateAtTime450000));
});
});
});

View File

@ -1,107 +0,0 @@
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 CappedCrowdsale = artifacts.require('IndividuallyCappedCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');
contract('IndividuallyCappedCrowdsale', function ([_, wallet, alice, bob, charlie]) {
const rate = new BigNumber(1);
const capAlice = ether(10);
const capBob = ether(2);
const lessThanCapAlice = ether(6);
const lessThanCapBoth = ether(1);
const tokenSupply = new BigNumber('1e22');
describe('individual capping', function () {
beforeEach(async function () {
this.token = await SimpleToken.new();
this.crowdsale = await CappedCrowdsale.new(rate, wallet, this.token.address);
await this.crowdsale.setUserCap(alice, capAlice);
await this.crowdsale.setUserCap(bob, capBob);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
describe('accepting payments', function () {
it('should accept payments within cap', async function () {
await this.crowdsale.buyTokens(alice, { value: lessThanCapAlice }).should.be.fulfilled;
await this.crowdsale.buyTokens(bob, { value: lessThanCapBoth }).should.be.fulfilled;
});
it('should reject payments outside cap', async function () {
await this.crowdsale.buyTokens(alice, { value: capAlice });
await this.crowdsale.buyTokens(alice, { value: 1 }).should.be.rejectedWith(EVMRevert);
});
it('should reject payments that exceed cap', async function () {
await this.crowdsale.buyTokens(alice, { value: capAlice.plus(1) }).should.be.rejectedWith(EVMRevert);
await this.crowdsale.buyTokens(bob, { value: capBob.plus(1) }).should.be.rejectedWith(EVMRevert);
});
it('should manage independent caps', async function () {
await this.crowdsale.buyTokens(alice, { value: lessThanCapAlice }).should.be.fulfilled;
await this.crowdsale.buyTokens(bob, { value: lessThanCapAlice }).should.be.rejectedWith(EVMRevert);
});
it('should default to a cap of zero', async function () {
await this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth }).should.be.rejectedWith(EVMRevert);
});
});
describe('reporting state', function () {
it('should report correct cap', async function () {
let retrievedCap = await this.crowdsale.getUserCap(alice);
retrievedCap.should.be.bignumber.equal(capAlice);
});
it('should report actual contribution', async function () {
await this.crowdsale.buyTokens(alice, { value: lessThanCapAlice });
let retrievedContribution = await this.crowdsale.getUserContribution(alice);
retrievedContribution.should.be.bignumber.equal(lessThanCapAlice);
});
});
});
describe('group capping', function () {
beforeEach(async function () {
this.token = await SimpleToken.new();
this.crowdsale = await CappedCrowdsale.new(rate, wallet, this.token.address);
await this.crowdsale.setGroupCap([bob, charlie], capBob);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
describe('accepting payments', function () {
it('should accept payments within cap', async function () {
await this.crowdsale.buyTokens(bob, { value: lessThanCapBoth }).should.be.fulfilled;
await this.crowdsale.buyTokens(charlie, { value: lessThanCapBoth }).should.be.fulfilled;
});
it('should reject payments outside cap', async function () {
await this.crowdsale.buyTokens(bob, { value: capBob });
await this.crowdsale.buyTokens(bob, { value: 1 }).should.be.rejectedWith(EVMRevert);
await this.crowdsale.buyTokens(charlie, { value: capBob });
await this.crowdsale.buyTokens(charlie, { value: 1 }).should.be.rejectedWith(EVMRevert);
});
it('should reject payments that exceed cap', async function () {
await this.crowdsale.buyTokens(bob, { value: capBob.plus(1) }).should.be.rejectedWith(EVMRevert);
await this.crowdsale.buyTokens(charlie, { value: capBob.plus(1) }).should.be.rejectedWith(EVMRevert);
});
});
describe('reporting state', function () {
it('should report correct cap', async function () {
let retrievedCapBob = await this.crowdsale.getUserCap(bob);
retrievedCapBob.should.be.bignumber.equal(capBob);
let retrievedCapCharlie = await this.crowdsale.getUserCap(charlie);
retrievedCapCharlie.should.be.bignumber.equal(capBob);
});
});
});
});

View File

@ -1,61 +0,0 @@
import ether from '../helpers/ether';
const BigNumber = web3.BigNumber;
const should = require('chai')
.use(require('chai-as-promised'))
.use(require('chai-bignumber')(BigNumber))
.should();
const MintedCrowdsale = artifacts.require('MintedCrowdsaleImpl');
const MintableToken = artifacts.require('MintableToken');
contract('MintedCrowdsale', function ([_, investor, wallet, purchaser]) {
const rate = new BigNumber(1000);
const value = ether(42);
const expectedTokenAmount = rate.mul(value);
beforeEach(async function () {
this.token = await MintableToken.new();
this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address);
await this.token.transferOwnership(this.crowdsale.address);
});
describe('accepting payments', function () {
it('should be token owner', async function () {
const owner = await this.token.owner();
owner.should.equal(this.crowdsale.address);
});
it('should accept payments', async function () {
await this.crowdsale.send(value).should.be.fulfilled;
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }).should.be.fulfilled;
});
});
describe('high-level purchase', function () {
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 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);
});
});
});

View File

@ -1,67 +0,0 @@
import { advanceBlock } from '../helpers/advanceToBlock';
import { increaseTimeTo, duration } from '../helpers/increaseTime';
import latestTime from '../helpers/latestTime';
import EVMRevert from '../helpers/EVMRevert';
import ether from '../helpers/ether';
const BigNumber = web3.BigNumber;
require('chai')
.use(require('chai-as-promised'))
.use(require('chai-bignumber')(BigNumber))
.should();
const PostDeliveryCrowdsale = artifacts.require('PostDeliveryCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');
contract('PostDeliveryCrowdsale', function ([_, investor, wallet, purchaser]) {
const rate = new BigNumber(1);
const value = ether(42);
const tokenSupply = new BigNumber('1e22');
before(async function () {
// Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache
await advanceBlock();
});
beforeEach(async function () {
this.openingTime = latestTime() + duration.weeks(1);
this.closingTime = this.openingTime + duration.weeks(1);
this.beforeEndTime = this.closingTime - duration.hours(1);
this.afterClosingTime = this.closingTime + duration.seconds(1);
this.token = await SimpleToken.new();
this.crowdsale = await PostDeliveryCrowdsale.new(
this.openingTime, this.closingTime, rate, wallet, this.token.address
);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
it('should not immediately assign tokens to beneficiary', async function () {
await increaseTimeTo(this.openingTime);
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser });
const balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(0);
});
it('should not allow beneficiaries to withdraw tokens before crowdsale ends', async function () {
await increaseTimeTo(this.beforeEndTime);
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser });
await this.crowdsale.withdrawTokens({ from: investor }).should.be.rejectedWith(EVMRevert);
});
it('should allow beneficiaries to withdraw tokens after crowdsale ends', async function () {
await increaseTimeTo(this.openingTime);
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser });
await increaseTimeTo(this.afterClosingTime);
await this.crowdsale.withdrawTokens({ from: investor }).should.be.fulfilled;
});
it('should return the amount of tokens bought', async function () {
await increaseTimeTo(this.openingTime);
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser });
await increaseTimeTo(this.afterClosingTime);
await this.crowdsale.withdrawTokens({ from: investor });
const balance = await this.token.balanceOf(investor);
balance.should.be.bignumber.equal(value);
});
});

View File

@ -1,59 +0,0 @@
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);
});
});

View File

@ -1,82 +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('RefundableCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');
contract('RefundableCrowdsale', function ([_, owner, wallet, investor, purchaser]) {
const rate = new BigNumber(1);
const goal = ether(50);
const lessThanGoal = ether(45);
const tokenSupply = new BigNumber('1e22');
before(async function () {
// Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache
await advanceBlock();
});
beforeEach(async function () {
this.openingTime = latestTime() + duration.weeks(1);
this.closingTime = this.openingTime + duration.weeks(1);
this.afterClosingTime = this.closingTime + duration.seconds(1);
this.token = await SimpleToken.new();
this.crowdsale = await RefundableCrowdsale.new(
this.openingTime, this.closingTime, rate, wallet, this.token.address, goal, { from: owner }
);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
describe('creating a valid crowdsale', function () {
it('should fail with zero goal', async function () {
await RefundableCrowdsale.new(
this.openingTime, this.closingTime, rate, wallet, this.token.address, 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.openingTime);
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.openingTime);
await this.crowdsale.sendTransaction({ value: goal, from: investor });
await increaseTimeTo(this.afterClosingTime);
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.openingTime);
await this.crowdsale.sendTransaction({ value: lessThanGoal, from: investor });
await increaseTimeTo(this.afterClosingTime);
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.openingTime);
await this.crowdsale.sendTransaction({ value: goal, from: investor });
await increaseTimeTo(this.afterClosingTime);
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);
});
});

View File

@ -1,62 +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 TimedCrowdsale = artifacts.require('TimedCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');
contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) {
const rate = new BigNumber(1);
const value = ether(42);
const tokenSupply = new BigNumber('1e22');
before(async function () {
// Advance to the next block to correctly read time in the solidity "now" function interpreted by ganache
await advanceBlock();
});
beforeEach(async function () {
this.openingTime = latestTime() + duration.weeks(1);
this.closingTime = this.openingTime + duration.weeks(1);
this.afterClosingTime = this.closingTime + duration.seconds(1);
this.token = await SimpleToken.new();
this.crowdsale = await TimedCrowdsale.new(this.openingTime, this.closingTime, rate, wallet, this.token.address);
await this.token.transfer(this.crowdsale.address, tokenSupply);
});
it('should be ended only after end', async function () {
let ended = await this.crowdsale.hasClosed();
ended.should.equal(false);
await increaseTimeTo(this.afterClosingTime);
ended = await this.crowdsale.hasClosed();
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.openingTime);
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.afterClosingTime);
await this.crowdsale.send(value).should.be.rejectedWith(EVMRevert);
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }).should.be.rejectedWith(EVMRevert);
});
});
});

Some files were not shown because too many files have changed in this diff Show More