diff --git a/contracts/RlnERC20.sol b/contracts/RlnERC20.sol
index 23197e9..7193926 100644
--- a/contracts/RlnERC20.sol
+++ b/contracts/RlnERC20.sol
@@ -1,6 +1,7 @@
pragma solidity 0.7.4;
import { IPoseidonHasher } from "./PoseidonHasher.sol";
+import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract RLN {
uint256 public immutable MEMBERSHIP_DEPOSIT;
@@ -27,7 +28,7 @@ contract RLN {
DEPTH = depth;
SET_SIZE = 1 << depth;
poseidonHasher = IPoseidonHasher(_poseidonHasher);
- AcceptedToken = IERC20(_acceptedTokenAddress)
+ AcceptedToken = IERC20(_acceptedTokenAddress);
}
function registerWithAcceptedToken(uint256 deposit, uint256 pubkey) external payable {
@@ -89,7 +90,7 @@ contract RLN {
members[_pubkeyIndex] = 0;
// refund deposit
- AcceptedToken.transferFrom(address(this),receiver,MEMBERSHIP_DEPOSIT)
+ AcceptedToken.transferFrom(address(this),receiver,MEMBERSHIP_DEPOSIT);
emit MemberWithdrawn(pubkey, _pubkeyIndex);
}
diff --git a/contracts/SntContract.sol b/contracts/SntContract.sol
index 4ccd833..5f5515c 100644
--- a/contracts/SntContract.sol
+++ b/contracts/SntContract.sol
@@ -1,1847 +1,1847 @@
-/**
- *Submitted for verification at Etherscan.io on 2017-06-19
-*/
-
-pragma solidity ^0.4.11;
-
-
-/// @dev `Owned` is a base level contract that assigns an `owner` that can be
-/// later changed
-contract Owned {
-
- /// @dev `owner` is the only address that can call a function with this
- /// modifier
- modifier onlyOwner() {
- require(msg.sender == owner);
- _;
- }
-
- address public owner;
-
- /// @notice The Constructor assigns the message sender to be `owner`
- function Owned() {
- owner = msg.sender;
- }
-
- address public newOwner;
-
- /// @notice `owner` can step down and assign some other address to this role
- /// @param _newOwner The address of the new owner. 0x0 can be used to create
- /// an unowned neutral vault, however that cannot be undone
- function changeOwner(address _newOwner) onlyOwner {
- newOwner = _newOwner;
- }
-
-
- function acceptOwnership() {
- if (msg.sender == newOwner) {
- owner = newOwner;
- }
- }
-}
-
-// Abstract contract for the full ERC 20 Token standard
-// https://github.com/ethereum/EIPs/issues/20
-
-contract ERC20Token {
- /* This is a slight change to the ERC20 base standard.
- function totalSupply() constant returns (uint256 supply);
- is replaced with:
- uint256 public totalSupply;
- This automatically creates a getter function for the totalSupply.
- This is moved to the base contract since public getter functions are not
- currently recognised as an implementation of the matching abstract
- function by the compiler.
- */
- /// total amount of tokens
- uint256 public totalSupply;
-
- /// @param _owner The address from which the balance will be retrieved
- /// @return The balance
- function balanceOf(address _owner) constant returns (uint256 balance);
-
- /// @notice send `_value` token to `_to` from `msg.sender`
- /// @param _to The address of the recipient
- /// @param _value The amount of token to be transferred
- /// @return Whether the transfer was successful or not
- function transfer(address _to, uint256 _value) returns (bool success);
-
- /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
- /// @param _from The address of the sender
- /// @param _to The address of the recipient
- /// @param _value The amount of token to be transferred
- /// @return Whether the transfer was successful or not
- function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
-
- /// @notice `msg.sender` approves `_spender` to spend `_value` tokens
- /// @param _spender The address of the account able to transfer the tokens
- /// @param _value The amount of tokens to be approved for transfer
- /// @return Whether the approval was successful or not
- function approve(address _spender, uint256 _value) returns (bool success);
-
- /// @param _owner The address of the account owning tokens
- /// @param _spender The address of the account able to transfer the tokens
- /// @return Amount of remaining tokens allowed to spent
- function allowance(address _owner, address _spender) constant returns (uint256 remaining);
-
- event Transfer(address indexed _from, address indexed _to, uint256 _value);
- event Approval(address indexed _owner, address indexed _spender, uint256 _value);
-}
-
-
-
-/**
- * Math operations with safety checks
- */
-library SafeMath {
- function mul(uint a, uint b) internal returns (uint) {
- uint c = a * b;
- assert(a == 0 || c / a == b);
- return c;
- }
-
- function div(uint a, uint b) internal returns (uint) {
- // assert(b > 0); // Solidity automatically throws when dividing by 0
- uint c = a / b;
- // assert(a == b * c + a % b); // There is no case in which this doesn't hold
- return c;
- }
-
- function sub(uint a, uint b) internal returns (uint) {
- assert(b <= a);
- return a - b;
- }
-
- function add(uint a, uint b) internal returns (uint) {
- uint c = a + b;
- assert(c >= a);
- return c;
- }
-
- function max64(uint64 a, uint64 b) internal constant returns (uint64) {
- return a >= b ? a : b;
- }
-
- function min64(uint64 a, uint64 b) internal constant returns (uint64) {
- return a < b ? a : b;
- }
-
- function max256(uint256 a, uint256 b) internal constant returns (uint256) {
- return a >= b ? a : b;
- }
-
- function min256(uint256 a, uint256 b) internal constant returns (uint256) {
- return a < b ? a : b;
- }
-}
-
-
-/*
- Copyright 2017, Jordi Baylina
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- */
-
-/// @title DynamicCeiling Contract
-/// @author Jordi Baylina
-/// @dev This contract calculates the ceiling from a series of curves.
-/// These curves are committed first and revealed later.
-/// All the curves must be in increasing order and the last curve is marked
-/// as the last one.
-/// This contract allows to hide and reveal the ceiling at will of the owner.
-
-
-
-contract DynamicCeiling is Owned {
- using SafeMath for uint256;
-
- struct Curve {
- bytes32 hash;
- // Absolute limit for this curve
- uint256 limit;
- // The funds remaining to be collected are divided by `slopeFactor` smooth ceiling
- // with a long tail where big and small buyers can take part.
- uint256 slopeFactor;
- // This keeps the curve flat at this number, until funds to be collected is less than this
- uint256 collectMinimum;
- }
-
- address public contribution;
-
- Curve[] public curves;
- uint256 public currentIndex;
- uint256 public revealedCurves;
- bool public allRevealed;
-
- /// @dev `contribution` is the only address that can call a function with this
- /// modifier
- modifier onlyContribution {
- require(msg.sender == contribution);
- _;
- }
-
- function DynamicCeiling(address _owner, address _contribution) {
- owner = _owner;
- contribution = _contribution;
- }
-
- /// @notice This should be called by the creator of the contract to commit
- /// all the curves.
- /// @param _curveHashes Array of hashes of each curve. Each hash is calculated
- /// by the `calculateHash` method. More hashes than actual curves can be
- /// committed in order to hide also the number of curves.
- /// The remaining hashes can be just random numbers.
- function setHiddenCurves(bytes32[] _curveHashes) public onlyOwner {
- require(curves.length == 0);
-
- curves.length = _curveHashes.length;
- for (uint256 i = 0; i < _curveHashes.length; i = i.add(1)) {
- curves[i].hash = _curveHashes[i];
- }
- }
-
-
- /// @notice Anybody can reveal the next curve if he knows it.
- /// @param _limit Ceiling cap.
- /// (must be greater or equal to the previous one).
- /// @param _last `true` if it's the last curve.
- /// @param _salt Random number used to commit the curve
- function revealCurve(uint256 _limit, uint256 _slopeFactor, uint256 _collectMinimum,
- bool _last, bytes32 _salt) public {
- require(!allRevealed);
-
- require(curves[revealedCurves].hash == calculateHash(_limit, _slopeFactor, _collectMinimum,
- _last, _salt));
-
- require(_limit != 0 && _slopeFactor != 0 && _collectMinimum != 0);
- if (revealedCurves > 0) {
- require(_limit >= curves[revealedCurves.sub(1)].limit);
- }
-
- curves[revealedCurves].limit = _limit;
- curves[revealedCurves].slopeFactor = _slopeFactor;
- curves[revealedCurves].collectMinimum = _collectMinimum;
- revealedCurves = revealedCurves.add(1);
-
- if (_last) allRevealed = true;
- }
-
- /// @notice Reveal multiple curves at once
- function revealMulti(uint256[] _limits, uint256[] _slopeFactors, uint256[] _collectMinimums,
- bool[] _lasts, bytes32[] _salts) public {
- // Do not allow none and needs to be same length for all parameters
- require(_limits.length != 0 &&
- _limits.length == _slopeFactors.length &&
- _limits.length == _collectMinimums.length &&
- _limits.length == _lasts.length &&
- _limits.length == _salts.length);
-
- for (uint256 i = 0; i < _limits.length; i = i.add(1)) {
- revealCurve(_limits[i], _slopeFactors[i], _collectMinimums[i],
- _lasts[i], _salts[i]);
- }
- }
-
- /// @notice Move to curve, used as a failsafe
- function moveTo(uint256 _index) public onlyOwner {
- require(_index < revealedCurves && // No more curves
- _index == currentIndex.add(1)); // Only move one index at a time
- currentIndex = _index;
- }
-
- /// @return Return the funds to collect for the current point on the curve
- /// (or 0 if no curves revealed yet)
- function toCollect(uint256 collected) public onlyContribution returns (uint256) {
- if (revealedCurves == 0) return 0;
-
- // Move to the next curve
- if (collected >= curves[currentIndex].limit) { // Catches `limit == 0`
- uint256 nextIndex = currentIndex.add(1);
- if (nextIndex >= revealedCurves) return 0; // No more curves
- currentIndex = nextIndex;
- if (collected >= curves[currentIndex].limit) return 0; // Catches `limit == 0`
- }
-
- // Everything left to collect from this limit
- uint256 difference = curves[currentIndex].limit.sub(collected);
-
- // Current point on the curve
- uint256 collect = difference.div(curves[currentIndex].slopeFactor);
-
- // Prevents paying too much fees vs to be collected; breaks long tail
- if (collect <= curves[currentIndex].collectMinimum) {
- if (difference > curves[currentIndex].collectMinimum) {
- return curves[currentIndex].collectMinimum;
- } else {
- return difference;
- }
- } else {
- return collect;
- }
- }
-
- /// @notice Calculates the hash of a curve.
- /// @param _limit Ceiling cap.
- /// @param _last `true` if it's the last curve.
- /// @param _salt Random number that will be needed to reveal this curve.
- /// @return The calculated hash of this curve to be used in the `setHiddenCurves` method
- function calculateHash(uint256 _limit, uint256 _slopeFactor, uint256 _collectMinimum,
- bool _last, bytes32 _salt) public constant returns (bytes32) {
- return keccak256(_limit, _slopeFactor, _collectMinimum, _last, _salt);
- }
-
- /// @return Return the total number of curves committed
- /// (can be larger than the number of actual curves on the curve to hide
- /// the real number of curves)
- function nCurves() public constant returns (uint256) {
- return curves.length;
- }
-
-}
-
-
-/*
- Copyright 2016, Jordi Baylina
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- */
-
-/// @title MiniMeToken Contract
-/// @author Jordi Baylina
-/// @dev This token contract's goal is to make it easy for anyone to clone this
-/// token using the token distribution at a given block, this will allow DAO's
-/// and DApps to upgrade their features in a decentralized manner without
-/// affecting the original token
-/// @dev It is ERC20 compliant, but still needs to under go further testing.
-
-
-/// @dev The token controller contract must implement these functions
-contract TokenController {
- /// @notice Called when `_owner` sends ether to the MiniMe Token contract
- /// @param _owner The address that sent the ether to create tokens
- /// @return True if the ether is accepted, false if it throws
- function proxyPayment(address _owner) payable returns(bool);
-
- /// @notice Notifies the controller about a token transfer allowing the
- /// controller to react if desired
- /// @param _from The origin of the transfer
- /// @param _to The destination of the transfer
- /// @param _amount The amount of the transfer
- /// @return False if the controller does not authorize the transfer
- function onTransfer(address _from, address _to, uint _amount) returns(bool);
-
- /// @notice Notifies the controller about an approval allowing the
- /// controller to react if desired
- /// @param _owner The address that calls `approve()`
- /// @param _spender The spender in the `approve()` call
- /// @param _amount The amount in the `approve()` call
- /// @return False if the controller does not authorize the approval
- function onApprove(address _owner, address _spender, uint _amount)
- returns(bool);
-}
-
-contract Controlled {
- /// @notice The address of the controller is the only address that can call
- /// a function with this modifier
- modifier onlyController { if (msg.sender != controller) throw; _; }
-
- address public controller;
-
- function Controlled() { controller = msg.sender;}
-
- /// @notice Changes the controller of the contract
- /// @param _newController The new controller of the contract
- function changeController(address _newController) onlyController {
- controller = _newController;
- }
-}
-
-contract ApproveAndCallFallBack {
- function receiveApproval(address from, uint256 _amount, address _token, bytes _data);
-}
-
-/// @dev The actual token contract, the default controller is the msg.sender
-/// that deploys the contract, so usually this token will be deployed by a
-/// token controller contract, which Giveth will call a "Campaign"
-contract MiniMeToken is Controlled {
-
- string public name; //The Token's name: e.g. DigixDAO Tokens
- uint8 public decimals; //Number of decimals of the smallest unit
- string public symbol; //An identifier: e.g. REP
- string public version = 'MMT_0.1'; //An arbitrary versioning scheme
-
-
- /// @dev `Checkpoint` is the structure that attaches a block number to a
- /// given value, the block number attached is the one that last changed the
- /// value
- struct Checkpoint {
-
- // `fromBlock` is the block number that the value was generated from
- uint128 fromBlock;
-
- // `value` is the amount of tokens at a specific block number
- uint128 value;
- }
-
- // `parentToken` is the Token address that was cloned to produce this token;
- // it will be 0x0 for a token that was not cloned
- MiniMeToken public parentToken;
-
- // `parentSnapShotBlock` is the block number from the Parent Token that was
- // used to determine the initial distribution of the Clone Token
- uint public parentSnapShotBlock;
-
- // `creationBlock` is the block number that the Clone Token was created
- uint public creationBlock;
-
- // `balances` is the map that tracks the balance of each address, in this
- // contract when the balance changes the block number that the change
- // occurred is also included in the map
- mapping (address => Checkpoint[]) balances;
-
- // `allowed` tracks any extra transfer rights as in all ERC20 tokens
- mapping (address => mapping (address => uint256)) allowed;
-
- // Tracks the history of the `totalSupply` of the token
- Checkpoint[] totalSupplyHistory;
-
- // Flag that determines if the token is transferable or not.
- bool public transfersEnabled;
-
- // The factory used to create new clone tokens
- MiniMeTokenFactory public tokenFactory;
-
-////////////////
-// Constructor
-////////////////
-
- /// @notice Constructor to create a MiniMeToken
- /// @param _tokenFactory The address of the MiniMeTokenFactory contract that
- /// will create the Clone token contracts, the token factory needs to be
- /// deployed first
- /// @param _parentToken Address of the parent token, set to 0x0 if it is a
- /// new token
- /// @param _parentSnapShotBlock Block of the parent token that will
- /// determine the initial distribution of the clone token, set to 0 if it
- /// is a new token
- /// @param _tokenName Name of the new token
- /// @param _decimalUnits Number of decimals of the new token
- /// @param _tokenSymbol Token Symbol for the new token
- /// @param _transfersEnabled If true, tokens will be able to be transferred
- function MiniMeToken(
- address _tokenFactory,
- address _parentToken,
- uint _parentSnapShotBlock,
- string _tokenName,
- uint8 _decimalUnits,
- string _tokenSymbol,
- bool _transfersEnabled
- ) {
- tokenFactory = MiniMeTokenFactory(_tokenFactory);
- name = _tokenName; // Set the name
- decimals = _decimalUnits; // Set the decimals
- symbol = _tokenSymbol; // Set the symbol
- parentToken = MiniMeToken(_parentToken);
- parentSnapShotBlock = _parentSnapShotBlock;
- transfersEnabled = _transfersEnabled;
- creationBlock = getBlockNumber();
- }
-
-
-///////////////////
-// ERC20 Methods
-///////////////////
-
- /// @notice Send `_amount` tokens to `_to` from `msg.sender`
- /// @param _to The address of the recipient
- /// @param _amount The amount of tokens to be transferred
- /// @return Whether the transfer was successful or not
- function transfer(address _to, uint256 _amount) returns (bool success) {
- if (!transfersEnabled) throw;
- return doTransfer(msg.sender, _to, _amount);
- }
-
- /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
- /// is approved by `_from`
- /// @param _from The address holding the tokens being transferred
- /// @param _to The address of the recipient
- /// @param _amount The amount of tokens to be transferred
- /// @return True if the transfer was successful
- function transferFrom(address _from, address _to, uint256 _amount
- ) returns (bool success) {
-
- // The controller of this contract can move tokens around at will,
- // this is important to recognize! Confirm that you trust the
- // controller of this contract, which in most situations should be
- // another open source smart contract or 0x0
- if (msg.sender != controller) {
- if (!transfersEnabled) throw;
-
- // The standard ERC 20 transferFrom functionality
- if (allowed[_from][msg.sender] < _amount) return false;
- allowed[_from][msg.sender] -= _amount;
- }
- return doTransfer(_from, _to, _amount);
- }
-
- /// @dev This is the actual transfer function in the token contract, it can
- /// only be called by other functions in this contract.
- /// @param _from The address holding the tokens being transferred
- /// @param _to The address of the recipient
- /// @param _amount The amount of tokens to be transferred
- /// @return True if the transfer was successful
- function doTransfer(address _from, address _to, uint _amount
- ) internal returns(bool) {
-
- if (_amount == 0) {
- return true;
- }
-
- if (parentSnapShotBlock >= getBlockNumber()) throw;
-
- // Do not allow transfer to 0x0 or the token contract itself
- if ((_to == 0) || (_to == address(this))) throw;
-
- // If the amount being transfered is more than the balance of the
- // account the transfer returns false
- var previousBalanceFrom = balanceOfAt(_from, getBlockNumber());
- if (previousBalanceFrom < _amount) {
- return false;
- }
-
- // Alerts the token controller of the transfer
- if (isContract(controller)) {
- if (!TokenController(controller).onTransfer(_from, _to, _amount))
- throw;
- }
-
- // First update the balance array with the new value for the address
- // sending the tokens
- updateValueAtNow(balances[_from], previousBalanceFrom - _amount);
-
- // Then update the balance array with the new value for the address
- // receiving the tokens
- var previousBalanceTo = balanceOfAt(_to, getBlockNumber());
- if (previousBalanceTo + _amount < previousBalanceTo) throw; // Check for overflow
- updateValueAtNow(balances[_to], previousBalanceTo + _amount);
-
- // An event to make the transfer easy to find on the blockchain
- Transfer(_from, _to, _amount);
-
- return true;
- }
-
- /// @param _owner The address that's balance is being requested
- /// @return The balance of `_owner` at the current block
- function balanceOf(address _owner) constant returns (uint256 balance) {
- return balanceOfAt(_owner, getBlockNumber());
- }
-
- /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
- /// its behalf. This is a modified version of the ERC20 approve function
- /// to be a little bit safer
- /// @param _spender The address of the account able to transfer the tokens
- /// @param _amount The amount of tokens to be approved for transfer
- /// @return True if the approval was successful
- function approve(address _spender, uint256 _amount) returns (bool success) {
- if (!transfersEnabled) throw;
-
- // To change the approve amount you first have to reduce the addresses`
- // allowance to zero by calling `approve(_spender,0)` if it is not
- // already 0 to mitigate the race condition described here:
- // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
- if ((_amount!=0) && (allowed[msg.sender][_spender] !=0)) throw;
-
- // Alerts the token controller of the approve function call
- if (isContract(controller)) {
- if (!TokenController(controller).onApprove(msg.sender, _spender, _amount))
- throw;
- }
-
- allowed[msg.sender][_spender] = _amount;
- Approval(msg.sender, _spender, _amount);
- return true;
- }
-
- /// @dev This function makes it easy to read the `allowed[]` map
- /// @param _owner The address of the account that owns the token
- /// @param _spender The address of the account able to transfer the tokens
- /// @return Amount of remaining tokens of _owner that _spender is allowed
- /// to spend
- function allowance(address _owner, address _spender
- ) constant returns (uint256 remaining) {
- return allowed[_owner][_spender];
- }
-
- /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
- /// its behalf, and then a function is triggered in the contract that is
- /// being approved, `_spender`. This allows users to use their tokens to
- /// interact with contracts in one function call instead of two
- /// @param _spender The address of the contract able to transfer the tokens
- /// @param _amount The amount of tokens to be approved for transfer
- /// @return True if the function call was successful
- function approveAndCall(address _spender, uint256 _amount, bytes _extraData
- ) returns (bool success) {
- if (!approve(_spender, _amount)) throw;
-
- ApproveAndCallFallBack(_spender).receiveApproval(
- msg.sender,
- _amount,
- this,
- _extraData
- );
-
- return true;
- }
-
- /// @dev This function makes it easy to get the total number of tokens
- /// @return The total number of tokens
- function totalSupply() constant returns (uint) {
- return totalSupplyAt(getBlockNumber());
- }
-
-
-////////////////
-// Query balance and totalSupply in History
-////////////////
-
- /// @dev Queries the balance of `_owner` at a specific `_blockNumber`
- /// @param _owner The address from which the balance will be retrieved
- /// @param _blockNumber The block number when the balance is queried
- /// @return The balance at `_blockNumber`
- function balanceOfAt(address _owner, uint _blockNumber) constant
- returns (uint) {
-
- // These next few lines are used when the balance of the token is
- // requested before a check point was ever created for this token, it
- // requires that the `parentToken.balanceOfAt` be queried at the
- // genesis block for that token as this contains initial balance of
- // this token
- if ((balances[_owner].length == 0)
- || (balances[_owner][0].fromBlock > _blockNumber)) {
- if (address(parentToken) != 0) {
- return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock));
- } else {
- // Has no parent
- return 0;
- }
-
- // This will return the expected balance during normal situations
- } else {
- return getValueAt(balances[_owner], _blockNumber);
- }
- }
-
- /// @notice Total amount of tokens at a specific `_blockNumber`.
- /// @param _blockNumber The block number when the totalSupply is queried
- /// @return The total amount of tokens at `_blockNumber`
- function totalSupplyAt(uint _blockNumber) constant returns(uint) {
-
- // These next few lines are used when the totalSupply of the token is
- // requested before a check point was ever created for this token, it
- // requires that the `parentToken.totalSupplyAt` be queried at the
- // genesis block for this token as that contains totalSupply of this
- // token at this block number.
- if ((totalSupplyHistory.length == 0)
- || (totalSupplyHistory[0].fromBlock > _blockNumber)) {
- if (address(parentToken) != 0) {
- return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock));
- } else {
- return 0;
- }
-
- // This will return the expected totalSupply during normal situations
- } else {
- return getValueAt(totalSupplyHistory, _blockNumber);
- }
- }
-
-////////////////
-// Clone Token Method
-////////////////
-
- /// @notice Creates a new clone token with the initial distribution being
- /// this token at `_snapshotBlock`
- /// @param _cloneTokenName Name of the clone token
- /// @param _cloneDecimalUnits Number of decimals of the smallest unit
- /// @param _cloneTokenSymbol Symbol of the clone token
- /// @param _snapshotBlock Block when the distribution of the parent token is
- /// copied to set the initial distribution of the new clone token;
- /// if the block is zero than the actual block, the current block is used
- /// @param _transfersEnabled True if transfers are allowed in the clone
- /// @return The address of the new MiniMeToken Contract
- function createCloneToken(
- string _cloneTokenName,
- uint8 _cloneDecimalUnits,
- string _cloneTokenSymbol,
- uint _snapshotBlock,
- bool _transfersEnabled
- ) returns(address) {
- if (_snapshotBlock == 0) _snapshotBlock = getBlockNumber();
- MiniMeToken cloneToken = tokenFactory.createCloneToken(
- this,
- _snapshotBlock,
- _cloneTokenName,
- _cloneDecimalUnits,
- _cloneTokenSymbol,
- _transfersEnabled
- );
-
- cloneToken.changeController(msg.sender);
-
- // An event to make the token easy to find on the blockchain
- NewCloneToken(address(cloneToken), _snapshotBlock);
- return address(cloneToken);
- }
-
-////////////////
-// Generate and destroy tokens
-////////////////
-
- /// @notice Generates `_amount` tokens that are assigned to `_owner`
- /// @param _owner The address that will be assigned the new tokens
- /// @param _amount The quantity of tokens generated
- /// @return True if the tokens are generated correctly
- function generateTokens(address _owner, uint _amount
- ) onlyController returns (bool) {
- uint curTotalSupply = getValueAt(totalSupplyHistory, getBlockNumber());
- if (curTotalSupply + _amount < curTotalSupply) throw; // Check for overflow
- updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
- var previousBalanceTo = balanceOf(_owner);
- if (previousBalanceTo + _amount < previousBalanceTo) throw; // Check for overflow
- updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
- Transfer(0, _owner, _amount);
- return true;
- }
-
-
- /// @notice Burns `_amount` tokens from `_owner`
- /// @param _owner The address that will lose the tokens
- /// @param _amount The quantity of tokens to burn
- /// @return True if the tokens are burned correctly
- function destroyTokens(address _owner, uint _amount
- ) onlyController returns (bool) {
- uint curTotalSupply = getValueAt(totalSupplyHistory, getBlockNumber());
- if (curTotalSupply < _amount) throw;
- updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
- var previousBalanceFrom = balanceOf(_owner);
- if (previousBalanceFrom < _amount) throw;
- updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
- Transfer(_owner, 0, _amount);
- return true;
- }
-
-////////////////
-// Enable tokens transfers
-////////////////
-
-
- /// @notice Enables token holders to transfer their tokens freely if true
- /// @param _transfersEnabled True if transfers are allowed in the clone
- function enableTransfers(bool _transfersEnabled) onlyController {
- transfersEnabled = _transfersEnabled;
- }
-
-////////////////
-// Internal helper functions to query and set a value in a snapshot array
-////////////////
-
- /// @dev `getValueAt` retrieves the number of tokens at a given block number
- /// @param checkpoints The history of values being queried
- /// @param _block The block number to retrieve the value at
- /// @return The number of tokens being queried
- function getValueAt(Checkpoint[] storage checkpoints, uint _block
- ) constant internal returns (uint) {
- if (checkpoints.length == 0) return 0;
-
- // Shortcut for the actual value
- if (_block >= checkpoints[checkpoints.length-1].fromBlock)
- return checkpoints[checkpoints.length-1].value;
- if (_block < checkpoints[0].fromBlock) return 0;
-
- // Binary search of the value in the array
- uint min = 0;
- uint max = checkpoints.length-1;
- while (max > min) {
- uint mid = (max + min + 1)/ 2;
- if (checkpoints[mid].fromBlock<=_block) {
- min = mid;
- } else {
- max = mid-1;
- }
- }
- return checkpoints[min].value;
- }
-
- /// @dev `updateValueAtNow` used to update the `balances` map and the
- /// `totalSupplyHistory`
- /// @param checkpoints The history of data being updated
- /// @param _value The new number of tokens
- function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value
- ) internal {
- if ((checkpoints.length == 0)
- || (checkpoints[checkpoints.length -1].fromBlock < getBlockNumber())) {
- Checkpoint newCheckPoint = checkpoints[ checkpoints.length++ ];
- newCheckPoint.fromBlock = uint128(getBlockNumber());
- newCheckPoint.value = uint128(_value);
- } else {
- Checkpoint oldCheckPoint = checkpoints[checkpoints.length-1];
- oldCheckPoint.value = uint128(_value);
- }
- }
-
- /// @dev Internal function to determine if an address is a contract
- /// @param _addr The address being queried
- /// @return True if `_addr` is a contract
- function isContract(address _addr) constant internal returns(bool) {
- uint size;
- if (_addr == 0) return false;
- assembly {
- size := extcodesize(_addr)
- }
- return size>0;
- }
-
- /// @dev Helper function to return a min betwen the two uints
- function min(uint a, uint b) internal returns (uint) {
- return a < b ? a : b;
- }
-
- /// @notice The fallback function: If the contract's controller has not been
- /// set to 0, then the `proxyPayment` method is called which relays the
- /// ether and creates tokens as described in the token controller contract
- function () payable {
- if (isContract(controller)) {
- if (! TokenController(controller).proxyPayment.value(msg.value)(msg.sender))
- throw;
- } else {
- throw;
- }
- }
-
-
-//////////
-// Testing specific methods
-//////////
-
- /// @notice This function is overridden by the test Mocks.
- function getBlockNumber() internal constant returns (uint256) {
- return block.number;
- }
-
-//////////
-// Safety Methods
-//////////
-
- /// @notice This method can be used by the controller to extract mistakenly
- /// sent tokens to this contract.
- /// @param _token The address of the token contract that you want to recover
- /// set to 0 in case you want to extract ether.
- function claimTokens(address _token) onlyController {
- if (_token == 0x0) {
- controller.transfer(this.balance);
- return;
- }
-
- ERC20Token token = ERC20Token(_token);
- uint balance = token.balanceOf(this);
- token.transfer(controller, balance);
- ClaimedTokens(_token, controller, balance);
- }
-
-////////////////
-// Events
-////////////////
-
- event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
- event Transfer(address indexed _from, address indexed _to, uint256 _amount);
- event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
- event Approval(
- address indexed _owner,
- address indexed _spender,
- uint256 _amount
- );
-
-}
-
-
-////////////////
-// MiniMeTokenFactory
-////////////////
-
-/// @dev This contract is used to generate clone contracts from a contract.
-/// In solidity this is the way to create a contract from a contract of the
-/// same class
-contract MiniMeTokenFactory {
-
- /// @notice Update the DApp by creating a new token with new functionalities
- /// the msg.sender becomes the controller of this clone token
- /// @param _parentToken Address of the token being cloned
- /// @param _snapshotBlock Block of the parent token that will
- /// determine the initial distribution of the clone token
- /// @param _tokenName Name of the new token
- /// @param _decimalUnits Number of decimals of the new token
- /// @param _tokenSymbol Token Symbol for the new token
- /// @param _transfersEnabled If true, tokens will be able to be transferred
- /// @return The address of the new token contract
- function createCloneToken(
- address _parentToken,
- uint _snapshotBlock,
- string _tokenName,
- uint8 _decimalUnits,
- string _tokenSymbol,
- bool _transfersEnabled
- ) returns (MiniMeToken) {
- MiniMeToken newToken = new MiniMeToken(
- this,
- _parentToken,
- _snapshotBlock,
- _tokenName,
- _decimalUnits,
- _tokenSymbol,
- _transfersEnabled
- );
-
- newToken.changeController(msg.sender);
- return newToken;
- }
-}
-
-
-/*
- Copyright 2017, Jarrad Hope (Status Research & Development GmbH)
-*/
-
-
-contract SNT is MiniMeToken {
- // @dev SNT constructor just parametrizes the MiniMeIrrevocableVestedToken constructor
- function SNT(address _tokenFactory)
- MiniMeToken(
- _tokenFactory,
- 0x0, // no parent token
- 0, // no snapshot block number from parent
- "Status Network Token", // Token name
- 18, // Decimals
- "SNT", // Symbol
- true // Enable transfers
- ) {}
-}
-
-
-/*
- Copyright 2017, Jordi Baylina
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- */
-
-/// @title StatusContribution Contract
-/// @author Jordi Baylina
-/// @dev This contract will be the SNT controller during the contribution period.
-/// This contract will determine the rules during this period.
-/// Final users will generally not interact directly with this contract. ETH will
-/// be sent to the SNT token contract. The ETH is sent to this contract and from here,
-/// ETH is sent to the contribution walled and SNTs are mined according to the defined
-/// rules.
-
-
-contract StatusContribution is Owned, TokenController {
- using SafeMath for uint256;
-
- uint256 constant public failSafeLimit = 300000 ether;
- uint256 constant public maxGuaranteedLimit = 30000 ether;
- uint256 constant public exchangeRate = 10000;
- uint256 constant public maxGasPrice = 50000000000;
- uint256 constant public maxCallFrequency = 100;
-
- MiniMeToken public SGT;
- MiniMeToken public SNT;
- uint256 public startBlock;
- uint256 public endBlock;
-
- address public destEthDevs;
-
- address public destTokensDevs;
- address public destTokensReserve;
- uint256 public maxSGTSupply;
- address public destTokensSgt;
- DynamicCeiling public dynamicCeiling;
-
- address public sntController;
-
- mapping (address => uint256) public guaranteedBuyersLimit;
- mapping (address => uint256) public guaranteedBuyersBought;
-
- uint256 public totalGuaranteedCollected;
- uint256 public totalNormalCollected;
-
- uint256 public finalizedBlock;
- uint256 public finalizedTime;
-
- mapping (address => uint256) public lastCallBlock;
-
- bool public paused;
-
- modifier initialized() {
- require(address(SNT) != 0x0);
- _;
- }
-
- modifier contributionOpen() {
- require(getBlockNumber() >= startBlock &&
- getBlockNumber() <= endBlock &&
- finalizedBlock == 0 &&
- address(SNT) != 0x0);
- _;
- }
-
- modifier notPaused() {
- require(!paused);
- _;
- }
-
- function StatusContribution() {
- paused = false;
- }
-
-
- /// @notice This method should be called by the owner before the contribution
- /// period starts This initializes most of the parameters
- /// @param _snt Address of the SNT token contract
- /// @param _sntController Token controller for the SNT that will be transferred after
- /// the contribution finalizes.
- /// @param _startBlock Block when the contribution period starts
- /// @param _endBlock The last block that the contribution period is active
- /// @param _dynamicCeiling Address of the contract that controls the ceiling
- /// @param _destEthDevs Destination address where the contribution ether is sent
- /// @param _destTokensReserve Address where the tokens for the reserve are sent
- /// @param _destTokensSgt Address of the exchanger SGT-SNT where the SNT are sent
- /// to be distributed to the SGT holders.
- /// @param _destTokensDevs Address where the tokens for the dev are sent
- /// @param _sgt Address of the SGT token contract
- /// @param _maxSGTSupply Quantity of SGT tokens that would represent 10% of status.
- function initialize(
- address _snt,
- address _sntController,
-
- uint256 _startBlock,
- uint256 _endBlock,
-
- address _dynamicCeiling,
-
- address _destEthDevs,
-
- address _destTokensReserve,
- address _destTokensSgt,
- address _destTokensDevs,
-
- address _sgt,
- uint256 _maxSGTSupply
- ) public onlyOwner {
- // Initialize only once
- require(address(SNT) == 0x0);
-
- SNT = MiniMeToken(_snt);
- require(SNT.totalSupply() == 0);
- require(SNT.controller() == address(this));
- require(SNT.decimals() == 18); // Same amount of decimals as ETH
-
- require(_sntController != 0x0);
- sntController = _sntController;
-
- require(_startBlock >= getBlockNumber());
- require(_startBlock < _endBlock);
- startBlock = _startBlock;
- endBlock = _endBlock;
-
- require(_dynamicCeiling != 0x0);
- dynamicCeiling = DynamicCeiling(_dynamicCeiling);
-
- require(_destEthDevs != 0x0);
- destEthDevs = _destEthDevs;
-
- require(_destTokensReserve != 0x0);
- destTokensReserve = _destTokensReserve;
-
- require(_destTokensSgt != 0x0);
- destTokensSgt = _destTokensSgt;
-
- require(_destTokensDevs != 0x0);
- destTokensDevs = _destTokensDevs;
-
- require(_sgt != 0x0);
- SGT = MiniMeToken(_sgt);
-
- require(_maxSGTSupply >= MiniMeToken(SGT).totalSupply());
- maxSGTSupply = _maxSGTSupply;
- }
-
- /// @notice Sets the limit for a guaranteed address. All the guaranteed addresses
- /// will be able to get SNTs during the contribution period with his own
- /// specific limit.
- /// This method should be called by the owner after the initialization
- /// and before the contribution starts.
- /// @param _th Guaranteed address
- /// @param _limit Limit for the guaranteed address.
- function setGuaranteedAddress(address _th, uint256 _limit) public initialized onlyOwner {
- require(getBlockNumber() < startBlock);
- require(_limit > 0 && _limit <= maxGuaranteedLimit);
- guaranteedBuyersLimit[_th] = _limit;
- GuaranteedAddress(_th, _limit);
- }
-
- /// @notice If anybody sends Ether directly to this contract, consider he is
- /// getting SNTs.
- function () public payable notPaused {
- proxyPayment(msg.sender);
- }
-
-
- //////////
- // MiniMe Controller functions
- //////////
-
- /// @notice This method will generally be called by the SNT token contract to
- /// acquire SNTs. Or directly from third parties that want to acquire SNTs in
- /// behalf of a token holder.
- /// @param _th SNT holder where the SNTs will be minted.
- function proxyPayment(address _th) public payable notPaused initialized contributionOpen returns (bool) {
- require(_th != 0x0);
- if (guaranteedBuyersLimit[_th] > 0) {
- buyGuaranteed(_th);
- } else {
- buyNormal(_th);
- }
- return true;
- }
-
- function onTransfer(address, address, uint256) public returns (bool) {
- return false;
- }
-
- function onApprove(address, address, uint256) public returns (bool) {
- return false;
- }
-
- function buyNormal(address _th) internal {
- require(tx.gasprice <= maxGasPrice);
-
- // Antispam mechanism
- address caller;
- if (msg.sender == address(SNT)) {
- caller = _th;
- } else {
- caller = msg.sender;
- }
-
- // Do not allow contracts to game the system
- require(!isContract(caller));
-
- require(getBlockNumber().sub(lastCallBlock[caller]) >= maxCallFrequency);
- lastCallBlock[caller] = getBlockNumber();
-
- uint256 toCollect = dynamicCeiling.toCollect(totalNormalCollected);
-
- uint256 toFund;
- if (msg.value <= toCollect) {
- toFund = msg.value;
- } else {
- toFund = toCollect;
- }
-
- totalNormalCollected = totalNormalCollected.add(toFund);
- doBuy(_th, toFund, false);
- }
-
- function buyGuaranteed(address _th) internal {
- uint256 toCollect = guaranteedBuyersLimit[_th];
-
- uint256 toFund;
- if (guaranteedBuyersBought[_th].add(msg.value) > toCollect) {
- toFund = toCollect.sub(guaranteedBuyersBought[_th]);
- } else {
- toFund = msg.value;
- }
-
- guaranteedBuyersBought[_th] = guaranteedBuyersBought[_th].add(toFund);
- totalGuaranteedCollected = totalGuaranteedCollected.add(toFund);
- doBuy(_th, toFund, true);
- }
-
- function doBuy(address _th, uint256 _toFund, bool _guaranteed) internal {
- assert(msg.value >= _toFund); // Not needed, but double check.
- assert(totalCollected() <= failSafeLimit);
-
- if (_toFund > 0) {
- uint256 tokensGenerated = _toFund.mul(exchangeRate);
- assert(SNT.generateTokens(_th, tokensGenerated));
- destEthDevs.transfer(_toFund);
- NewSale(_th, _toFund, tokensGenerated, _guaranteed);
- }
-
- uint256 toReturn = msg.value.sub(_toFund);
- if (toReturn > 0) {
- // If the call comes from the Token controller,
- // then we return it to the token Holder.
- // Otherwise we return to the sender.
- if (msg.sender == address(SNT)) {
- _th.transfer(toReturn);
- } else {
- msg.sender.transfer(toReturn);
- }
- }
- }
-
- // NOTE on Percentage format
- // Right now, Solidity does not support decimal numbers. (This will change very soon)
- // So in this contract we use a representation of a percentage that consist in
- // expressing the percentage in "x per 10**18"
- // This format has a precision of 16 digits for a percent.
- // Examples:
- // 3% = 3*(10**16)
- // 100% = 100*(10**16) = 10**18
- //
- // To get a percentage of a value we do it by first multiplying it by the percentage in (x per 10^18)
- // and then divide it by 10**18
- //
- // Y * X(in x per 10**18)
- // X% of Y = -------------------------
- // 100(in x per 10**18)
- //
-
-
- /// @notice This method will can be called by the owner before the contribution period
- /// end or by anybody after the `endBlock`. This method finalizes the contribution period
- /// by creating the remaining tokens and transferring the controller to the configured
- /// controller.
- function finalize() public initialized {
- require(getBlockNumber() >= startBlock);
- require(msg.sender == owner || getBlockNumber() > endBlock);
- require(finalizedBlock == 0);
-
- // Do not allow termination until all curves revealed.
- require(dynamicCeiling.allRevealed());
-
- // Allow premature finalization if final limit is reached
- if (getBlockNumber() <= endBlock) {
- var (,lastLimit,,) = dynamicCeiling.curves(dynamicCeiling.revealedCurves().sub(1));
- require(totalNormalCollected >= lastLimit);
- }
-
- finalizedBlock = getBlockNumber();
- finalizedTime = now;
-
- uint256 percentageToSgt;
- if (SGT.totalSupply() >= maxSGTSupply) {
- percentageToSgt = percent(10); // 10%
- } else {
-
- //
- // SGT.totalSupply()
- // percentageToSgt = 10% * -------------------
- // maxSGTSupply
- //
- percentageToSgt = percent(10).mul(SGT.totalSupply()).div(maxSGTSupply);
- }
-
- uint256 percentageToDevs = percent(20); // 20%
-
-
- //
- // % To Contributors = 41% + (10% - % to SGT holders)
- //
- uint256 percentageToContributors = percent(41).add(percent(10).sub(percentageToSgt));
-
- uint256 percentageToReserve = percent(29);
-
-
- // SNT.totalSupply() -> Tokens minted during the contribution
- // totalTokens -> Total tokens that should be after the allocation
- // of devTokens, sgtTokens and reserve
- // percentageToContributors -> Which percentage should go to the
- // contribution participants
- // (x per 10**18 format)
- // percent(100) -> 100% in (x per 10**18 format)
- //
- // percentageToContributors
- // SNT.totalSupply() = -------------------------- * totalTokens =>
- // percent(100)
- //
- //
- // percent(100)
- // => totalTokens = ---------------------------- * SNT.totalSupply()
- // percentageToContributors
- //
- uint256 totalTokens = SNT.totalSupply().mul(percent(100)).div(percentageToContributors);
-
-
- // Generate tokens for SGT Holders.
-
- //
- // percentageToReserve
- // reserveTokens = ----------------------- * totalTokens
- // percentage(100)
- //
- assert(SNT.generateTokens(
- destTokensReserve,
- totalTokens.mul(percentageToReserve).div(percent(100))));
-
- //
- // percentageToSgt
- // sgtTokens = ----------------------- * totalTokens
- // percentage(100)
- //
- assert(SNT.generateTokens(
- destTokensSgt,
- totalTokens.mul(percentageToSgt).div(percent(100))));
-
-
- //
- // percentageToDevs
- // devTokens = ----------------------- * totalTokens
- // percentage(100)
- //
- assert(SNT.generateTokens(
- destTokensDevs,
- totalTokens.mul(percentageToDevs).div(percent(100))));
-
- SNT.changeController(sntController);
-
- Finalized();
- }
-
- function percent(uint256 p) internal returns (uint256) {
- return p.mul(10**16);
- }
-
- /// @dev Internal function to determine if an address is a contract
- /// @param _addr The address being queried
- /// @return True if `_addr` is a contract
- function isContract(address _addr) constant internal returns (bool) {
- if (_addr == 0) return false;
- uint256 size;
- assembly {
- size := extcodesize(_addr)
- }
- return (size > 0);
- }
-
-
- //////////
- // Constant functions
- //////////
-
- /// @return Total tokens issued in weis.
- function tokensIssued() public constant returns (uint256) {
- return SNT.totalSupply();
- }
-
- /// @return Total Ether collected.
- function totalCollected() public constant returns (uint256) {
- return totalNormalCollected.add(totalGuaranteedCollected);
- }
-
-
- //////////
- // Testing specific methods
- //////////
-
- /// @notice This function is overridden by the test Mocks.
- function getBlockNumber() internal constant returns (uint256) {
- return block.number;
- }
-
-
- //////////
- // Safety Methods
- //////////
-
- /// @notice This method can be used by the controller to extract mistakenly
- /// sent tokens to this contract.
- /// @param _token The address of the token contract that you want to recover
- /// set to 0 in case you want to extract ether.
- function claimTokens(address _token) public onlyOwner {
- if (SNT.controller() == address(this)) {
- SNT.claimTokens(_token);
- }
- if (_token == 0x0) {
- owner.transfer(this.balance);
- return;
- }
-
- ERC20Token token = ERC20Token(_token);
- uint256 balance = token.balanceOf(this);
- token.transfer(owner, balance);
- ClaimedTokens(_token, owner, balance);
- }
-
-
- /// @notice Pauses the contribution if there is any issue
- function pauseContribution() onlyOwner {
- paused = true;
- }
-
- /// @notice Resumes the contribution
- function resumeContribution() onlyOwner {
- paused = false;
- }
-
- event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
- event NewSale(address indexed _th, uint256 _amount, uint256 _tokens, bool _guaranteed);
- event GuaranteedAddress(address indexed _th, uint256 _limit);
- event Finalized();
-}
-
-
-/*
- Copyright 2017, Jordi Baylina
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- */
-
-/// @title ContributionWallet Contract
-/// @author Jordi Baylina
-/// @dev This contract will be hold the Ether during the contribution period.
-/// The idea of this contract is to avoid recycling Ether during the contribution
-/// period. So all the ETH collected will be locked here until the contribution
-/// period ends
-
-// @dev Contract to hold sale raised funds during the sale period.
-// Prevents attack in which the Aragon Multisig sends raised ether
-// to the sale contract to mint tokens to itself, and getting the
-// funds back immediately.
-
-
-
-contract ContributionWallet {
-
- // Public variables
- address public multisig;
- uint256 public endBlock;
- StatusContribution public contribution;
-
- // @dev Constructor initializes public variables
- // @param _multisig The address of the multisig that will receive the funds
- // @param _endBlock Block after which the multisig can request the funds
- // @param _contribution Address of the StatusContribution contract
- function ContributionWallet(address _multisig, uint256 _endBlock, address _contribution) {
- require(_multisig != 0x0);
- require(_contribution != 0x0);
- require(_endBlock != 0 && _endBlock <= 4000000);
- multisig = _multisig;
- endBlock = _endBlock;
- contribution = StatusContribution(_contribution);
- }
-
- // @dev Receive all sent funds without any further logic
- function () public payable {}
-
- // @dev Withdraw function sends all the funds to the wallet if conditions are correct
- function withdraw() public {
- require(msg.sender == multisig); // Only the multisig can request it
- require(block.number > endBlock || // Allow after end block
- contribution.finalizedBlock() != 0); // Allow when sale is finalized
- multisig.transfer(this.balance);
- }
-
-}
-
-
-/*
- Copyright 2017, Jordi Baylina
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- */
+// /**
+// *Submitted for verification at Etherscan.io on 2017-06-19
+// */
+
+// pragma solidity ^0.4.11;
+
+
+// /// @dev `Owned` is a base level contract that assigns an `owner` that can be
+// /// later changed
+// contract Owned {
+
+// /// @dev `owner` is the only address that can call a function with this
+// /// modifier
+// modifier onlyOwner() {
+// require(msg.sender == owner);
+// _;
+// }
+
+// address public owner;
+
+// /// @notice The Constructor assigns the message sender to be `owner`
+// function Owned() {
+// owner = msg.sender;
+// }
+
+// address public newOwner;
+
+// /// @notice `owner` can step down and assign some other address to this role
+// /// @param _newOwner The address of the new owner. 0x0 can be used to create
+// /// an unowned neutral vault, however that cannot be undone
+// function changeOwner(address _newOwner) onlyOwner {
+// newOwner = _newOwner;
+// }
+
+
+// function acceptOwnership() {
+// if (msg.sender == newOwner) {
+// owner = newOwner;
+// }
+// }
+// }
+
+// // Abstract contract for the full ERC 20 Token standard
+// // https://github.com/ethereum/EIPs/issues/20
+
+// contract ERC20Token {
+// /* This is a slight change to the ERC20 base standard.
+// function totalSupply() constant returns (uint256 supply);
+// is replaced with:
+// uint256 public totalSupply;
+// This automatically creates a getter function for the totalSupply.
+// This is moved to the base contract since public getter functions are not
+// currently recognised as an implementation of the matching abstract
+// function by the compiler.
+// */
+// /// total amount of tokens
+// uint256 public totalSupply;
+
+// /// @param _owner The address from which the balance will be retrieved
+// /// @return The balance
+// function balanceOf(address _owner) constant returns (uint256 balance);
+
+// /// @notice send `_value` token to `_to` from `msg.sender`
+// /// @param _to The address of the recipient
+// /// @param _value The amount of token to be transferred
+// /// @return Whether the transfer was successful or not
+// function transfer(address _to, uint256 _value) returns (bool success);
+
+// /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
+// /// @param _from The address of the sender
+// /// @param _to The address of the recipient
+// /// @param _value The amount of token to be transferred
+// /// @return Whether the transfer was successful or not
+// function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
+
+// /// @notice `msg.sender` approves `_spender` to spend `_value` tokens
+// /// @param _spender The address of the account able to transfer the tokens
+// /// @param _value The amount of tokens to be approved for transfer
+// /// @return Whether the approval was successful or not
+// function approve(address _spender, uint256 _value) returns (bool success);
+
+// /// @param _owner The address of the account owning tokens
+// /// @param _spender The address of the account able to transfer the tokens
+// /// @return Amount of remaining tokens allowed to spent
+// function allowance(address _owner, address _spender) constant returns (uint256 remaining);
+
+// event Transfer(address indexed _from, address indexed _to, uint256 _value);
+// event Approval(address indexed _owner, address indexed _spender, uint256 _value);
+// }
+
+
+
+// /**
+// * Math operations with safety checks
+// */
+// library SafeMath {
+// function mul(uint a, uint b) internal returns (uint) {
+// uint c = a * b;
+// assert(a == 0 || c / a == b);
+// return c;
+// }
+
+// function div(uint a, uint b) internal returns (uint) {
+// // assert(b > 0); // Solidity automatically throws when dividing by 0
+// uint c = a / b;
+// // assert(a == b * c + a % b); // There is no case in which this doesn't hold
+// return c;
+// }
+
+// function sub(uint a, uint b) internal returns (uint) {
+// assert(b <= a);
+// return a - b;
+// }
+
+// function add(uint a, uint b) internal returns (uint) {
+// uint c = a + b;
+// assert(c >= a);
+// return c;
+// }
+
+// function max64(uint64 a, uint64 b) internal constant returns (uint64) {
+// return a >= b ? a : b;
+// }
+
+// function min64(uint64 a, uint64 b) internal constant returns (uint64) {
+// return a < b ? a : b;
+// }
+
+// function max256(uint256 a, uint256 b) internal constant returns (uint256) {
+// return a >= b ? a : b;
+// }
+
+// function min256(uint256 a, uint256 b) internal constant returns (uint256) {
+// return a < b ? a : b;
+// }
+// }
+
+
+// /*
+// Copyright 2017, Jordi Baylina
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// /// @title DynamicCeiling Contract
+// /// @author Jordi Baylina
+// /// @dev This contract calculates the ceiling from a series of curves.
+// /// These curves are committed first and revealed later.
+// /// All the curves must be in increasing order and the last curve is marked
+// /// as the last one.
+// /// This contract allows to hide and reveal the ceiling at will of the owner.
+
+
+
+// contract DynamicCeiling is Owned {
+// using SafeMath for uint256;
+
+// struct Curve {
+// bytes32 hash;
+// // Absolute limit for this curve
+// uint256 limit;
+// // The funds remaining to be collected are divided by `slopeFactor` smooth ceiling
+// // with a long tail where big and small buyers can take part.
+// uint256 slopeFactor;
+// // This keeps the curve flat at this number, until funds to be collected is less than this
+// uint256 collectMinimum;
+// }
+
+// address public contribution;
+
+// Curve[] public curves;
+// uint256 public currentIndex;
+// uint256 public revealedCurves;
+// bool public allRevealed;
+
+// /// @dev `contribution` is the only address that can call a function with this
+// /// modifier
+// modifier onlyContribution {
+// require(msg.sender == contribution);
+// _;
+// }
+
+// function DynamicCeiling(address _owner, address _contribution) {
+// owner = _owner;
+// contribution = _contribution;
+// }
+
+// /// @notice This should be called by the creator of the contract to commit
+// /// all the curves.
+// /// @param _curveHashes Array of hashes of each curve. Each hash is calculated
+// /// by the `calculateHash` method. More hashes than actual curves can be
+// /// committed in order to hide also the number of curves.
+// /// The remaining hashes can be just random numbers.
+// function setHiddenCurves(bytes32[] _curveHashes) public onlyOwner {
+// require(curves.length == 0);
+
+// curves.length = _curveHashes.length;
+// for (uint256 i = 0; i < _curveHashes.length; i = i.add(1)) {
+// curves[i].hash = _curveHashes[i];
+// }
+// }
+
+
+// /// @notice Anybody can reveal the next curve if he knows it.
+// /// @param _limit Ceiling cap.
+// /// (must be greater or equal to the previous one).
+// /// @param _last `true` if it's the last curve.
+// /// @param _salt Random number used to commit the curve
+// function revealCurve(uint256 _limit, uint256 _slopeFactor, uint256 _collectMinimum,
+// bool _last, bytes32 _salt) public {
+// require(!allRevealed);
+
+// require(curves[revealedCurves].hash == calculateHash(_limit, _slopeFactor, _collectMinimum,
+// _last, _salt));
+
+// require(_limit != 0 && _slopeFactor != 0 && _collectMinimum != 0);
+// if (revealedCurves > 0) {
+// require(_limit >= curves[revealedCurves.sub(1)].limit);
+// }
+
+// curves[revealedCurves].limit = _limit;
+// curves[revealedCurves].slopeFactor = _slopeFactor;
+// curves[revealedCurves].collectMinimum = _collectMinimum;
+// revealedCurves = revealedCurves.add(1);
+
+// if (_last) allRevealed = true;
+// }
+
+// /// @notice Reveal multiple curves at once
+// function revealMulti(uint256[] _limits, uint256[] _slopeFactors, uint256[] _collectMinimums,
+// bool[] _lasts, bytes32[] _salts) public {
+// // Do not allow none and needs to be same length for all parameters
+// require(_limits.length != 0 &&
+// _limits.length == _slopeFactors.length &&
+// _limits.length == _collectMinimums.length &&
+// _limits.length == _lasts.length &&
+// _limits.length == _salts.length);
+
+// for (uint256 i = 0; i < _limits.length; i = i.add(1)) {
+// revealCurve(_limits[i], _slopeFactors[i], _collectMinimums[i],
+// _lasts[i], _salts[i]);
+// }
+// }
+
+// /// @notice Move to curve, used as a failsafe
+// function moveTo(uint256 _index) public onlyOwner {
+// require(_index < revealedCurves && // No more curves
+// _index == currentIndex.add(1)); // Only move one index at a time
+// currentIndex = _index;
+// }
+
+// /// @return Return the funds to collect for the current point on the curve
+// /// (or 0 if no curves revealed yet)
+// function toCollect(uint256 collected) public onlyContribution returns (uint256) {
+// if (revealedCurves == 0) return 0;
+
+// // Move to the next curve
+// if (collected >= curves[currentIndex].limit) { // Catches `limit == 0`
+// uint256 nextIndex = currentIndex.add(1);
+// if (nextIndex >= revealedCurves) return 0; // No more curves
+// currentIndex = nextIndex;
+// if (collected >= curves[currentIndex].limit) return 0; // Catches `limit == 0`
+// }
+
+// // Everything left to collect from this limit
+// uint256 difference = curves[currentIndex].limit.sub(collected);
+
+// // Current point on the curve
+// uint256 collect = difference.div(curves[currentIndex].slopeFactor);
+
+// // Prevents paying too much fees vs to be collected; breaks long tail
+// if (collect <= curves[currentIndex].collectMinimum) {
+// if (difference > curves[currentIndex].collectMinimum) {
+// return curves[currentIndex].collectMinimum;
+// } else {
+// return difference;
+// }
+// } else {
+// return collect;
+// }
+// }
+
+// /// @notice Calculates the hash of a curve.
+// /// @param _limit Ceiling cap.
+// /// @param _last `true` if it's the last curve.
+// /// @param _salt Random number that will be needed to reveal this curve.
+// /// @return The calculated hash of this curve to be used in the `setHiddenCurves` method
+// function calculateHash(uint256 _limit, uint256 _slopeFactor, uint256 _collectMinimum,
+// bool _last, bytes32 _salt) public constant returns (bytes32) {
+// return keccak256(_limit, _slopeFactor, _collectMinimum, _last, _salt);
+// }
+
+// /// @return Return the total number of curves committed
+// /// (can be larger than the number of actual curves on the curve to hide
+// /// the real number of curves)
+// function nCurves() public constant returns (uint256) {
+// return curves.length;
+// }
+
+// }
+
+
+// /*
+// Copyright 2016, Jordi Baylina
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// /// @title MiniMeToken Contract
+// /// @author Jordi Baylina
+// /// @dev This token contract's goal is to make it easy for anyone to clone this
+// /// token using the token distribution at a given block, this will allow DAO's
+// /// and DApps to upgrade their features in a decentralized manner without
+// /// affecting the original token
+// /// @dev It is ERC20 compliant, but still needs to under go further testing.
+
+
+// /// @dev The token controller contract must implement these functions
+// contract TokenController {
+// /// @notice Called when `_owner` sends ether to the MiniMe Token contract
+// /// @param _owner The address that sent the ether to create tokens
+// /// @return True if the ether is accepted, false if it throws
+// function proxyPayment(address _owner) payable returns(bool);
+
+// /// @notice Notifies the controller about a token transfer allowing the
+// /// controller to react if desired
+// /// @param _from The origin of the transfer
+// /// @param _to The destination of the transfer
+// /// @param _amount The amount of the transfer
+// /// @return False if the controller does not authorize the transfer
+// function onTransfer(address _from, address _to, uint _amount) returns(bool);
+
+// /// @notice Notifies the controller about an approval allowing the
+// /// controller to react if desired
+// /// @param _owner The address that calls `approve()`
+// /// @param _spender The spender in the `approve()` call
+// /// @param _amount The amount in the `approve()` call
+// /// @return False if the controller does not authorize the approval
+// function onApprove(address _owner, address _spender, uint _amount)
+// returns(bool);
+// }
+
+// contract Controlled {
+// /// @notice The address of the controller is the only address that can call
+// /// a function with this modifier
+// modifier onlyController { if (msg.sender != controller) throw; _; }
+
+// address public controller;
+
+// function Controlled() { controller = msg.sender;}
+
+// /// @notice Changes the controller of the contract
+// /// @param _newController The new controller of the contract
+// function changeController(address _newController) onlyController {
+// controller = _newController;
+// }
+// }
+
+// contract ApproveAndCallFallBack {
+// function receiveApproval(address from, uint256 _amount, address _token, bytes _data);
+// }
+
+// /// @dev The actual token contract, the default controller is the msg.sender
+// /// that deploys the contract, so usually this token will be deployed by a
+// /// token controller contract, which Giveth will call a "Campaign"
+// contract MiniMeToken is Controlled {
+
+// string public name; //The Token's name: e.g. DigixDAO Tokens
+// uint8 public decimals; //Number of decimals of the smallest unit
+// string public symbol; //An identifier: e.g. REP
+// string public version = 'MMT_0.1'; //An arbitrary versioning scheme
+
+
+// /// @dev `Checkpoint` is the structure that attaches a block number to a
+// /// given value, the block number attached is the one that last changed the
+// /// value
+// struct Checkpoint {
+
+// // `fromBlock` is the block number that the value was generated from
+// uint128 fromBlock;
+
+// // `value` is the amount of tokens at a specific block number
+// uint128 value;
+// }
+
+// // `parentToken` is the Token address that was cloned to produce this token;
+// // it will be 0x0 for a token that was not cloned
+// MiniMeToken public parentToken;
+
+// // `parentSnapShotBlock` is the block number from the Parent Token that was
+// // used to determine the initial distribution of the Clone Token
+// uint public parentSnapShotBlock;
+
+// // `creationBlock` is the block number that the Clone Token was created
+// uint public creationBlock;
+
+// // `balances` is the map that tracks the balance of each address, in this
+// // contract when the balance changes the block number that the change
+// // occurred is also included in the map
+// mapping (address => Checkpoint[]) balances;
+
+// // `allowed` tracks any extra transfer rights as in all ERC20 tokens
+// mapping (address => mapping (address => uint256)) allowed;
+
+// // Tracks the history of the `totalSupply` of the token
+// Checkpoint[] totalSupplyHistory;
+
+// // Flag that determines if the token is transferable or not.
+// bool public transfersEnabled;
+
+// // The factory used to create new clone tokens
+// MiniMeTokenFactory public tokenFactory;
+
+// ////////////////
+// // Constructor
+// ////////////////
+
+// /// @notice Constructor to create a MiniMeToken
+// /// @param _tokenFactory The address of the MiniMeTokenFactory contract that
+// /// will create the Clone token contracts, the token factory needs to be
+// /// deployed first
+// /// @param _parentToken Address of the parent token, set to 0x0 if it is a
+// /// new token
+// /// @param _parentSnapShotBlock Block of the parent token that will
+// /// determine the initial distribution of the clone token, set to 0 if it
+// /// is a new token
+// /// @param _tokenName Name of the new token
+// /// @param _decimalUnits Number of decimals of the new token
+// /// @param _tokenSymbol Token Symbol for the new token
+// /// @param _transfersEnabled If true, tokens will be able to be transferred
+// function MiniMeToken(
+// address _tokenFactory,
+// address _parentToken,
+// uint _parentSnapShotBlock,
+// string _tokenName,
+// uint8 _decimalUnits,
+// string _tokenSymbol,
+// bool _transfersEnabled
+// ) {
+// tokenFactory = MiniMeTokenFactory(_tokenFactory);
+// name = _tokenName; // Set the name
+// decimals = _decimalUnits; // Set the decimals
+// symbol = _tokenSymbol; // Set the symbol
+// parentToken = MiniMeToken(_parentToken);
+// parentSnapShotBlock = _parentSnapShotBlock;
+// transfersEnabled = _transfersEnabled;
+// creationBlock = getBlockNumber();
+// }
+
+
+// ///////////////////
+// // ERC20 Methods
+// ///////////////////
+
+// /// @notice Send `_amount` tokens to `_to` from `msg.sender`
+// /// @param _to The address of the recipient
+// /// @param _amount The amount of tokens to be transferred
+// /// @return Whether the transfer was successful or not
+// function transfer(address _to, uint256 _amount) returns (bool success) {
+// if (!transfersEnabled) throw;
+// return doTransfer(msg.sender, _to, _amount);
+// }
+
+// /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
+// /// is approved by `_from`
+// /// @param _from The address holding the tokens being transferred
+// /// @param _to The address of the recipient
+// /// @param _amount The amount of tokens to be transferred
+// /// @return True if the transfer was successful
+// function transferFrom(address _from, address _to, uint256 _amount
+// ) returns (bool success) {
+
+// // The controller of this contract can move tokens around at will,
+// // this is important to recognize! Confirm that you trust the
+// // controller of this contract, which in most situations should be
+// // another open source smart contract or 0x0
+// if (msg.sender != controller) {
+// if (!transfersEnabled) throw;
+
+// // The standard ERC 20 transferFrom functionality
+// if (allowed[_from][msg.sender] < _amount) return false;
+// allowed[_from][msg.sender] -= _amount;
+// }
+// return doTransfer(_from, _to, _amount);
+// }
+
+// /// @dev This is the actual transfer function in the token contract, it can
+// /// only be called by other functions in this contract.
+// /// @param _from The address holding the tokens being transferred
+// /// @param _to The address of the recipient
+// /// @param _amount The amount of tokens to be transferred
+// /// @return True if the transfer was successful
+// function doTransfer(address _from, address _to, uint _amount
+// ) internal returns(bool) {
+
+// if (_amount == 0) {
+// return true;
+// }
+
+// if (parentSnapShotBlock >= getBlockNumber()) throw;
+
+// // Do not allow transfer to 0x0 or the token contract itself
+// if ((_to == 0) || (_to == address(this))) throw;
+
+// // If the amount being transfered is more than the balance of the
+// // account the transfer returns false
+// var previousBalanceFrom = balanceOfAt(_from, getBlockNumber());
+// if (previousBalanceFrom < _amount) {
+// return false;
+// }
+
+// // Alerts the token controller of the transfer
+// if (isContract(controller)) {
+// if (!TokenController(controller).onTransfer(_from, _to, _amount))
+// throw;
+// }
+
+// // First update the balance array with the new value for the address
+// // sending the tokens
+// updateValueAtNow(balances[_from], previousBalanceFrom - _amount);
+
+// // Then update the balance array with the new value for the address
+// // receiving the tokens
+// var previousBalanceTo = balanceOfAt(_to, getBlockNumber());
+// if (previousBalanceTo + _amount < previousBalanceTo) throw; // Check for overflow
+// updateValueAtNow(balances[_to], previousBalanceTo + _amount);
+
+// // An event to make the transfer easy to find on the blockchain
+// Transfer(_from, _to, _amount);
+
+// return true;
+// }
+
+// /// @param _owner The address that's balance is being requested
+// /// @return The balance of `_owner` at the current block
+// function balanceOf(address _owner) constant returns (uint256 balance) {
+// return balanceOfAt(_owner, getBlockNumber());
+// }
+
+// /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
+// /// its behalf. This is a modified version of the ERC20 approve function
+// /// to be a little bit safer
+// /// @param _spender The address of the account able to transfer the tokens
+// /// @param _amount The amount of tokens to be approved for transfer
+// /// @return True if the approval was successful
+// function approve(address _spender, uint256 _amount) returns (bool success) {
+// if (!transfersEnabled) throw;
+
+// // To change the approve amount you first have to reduce the addresses`
+// // allowance to zero by calling `approve(_spender,0)` if it is not
+// // already 0 to mitigate the race condition described here:
+// // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+// if ((_amount!=0) && (allowed[msg.sender][_spender] !=0)) throw;
+
+// // Alerts the token controller of the approve function call
+// if (isContract(controller)) {
+// if (!TokenController(controller).onApprove(msg.sender, _spender, _amount))
+// throw;
+// }
+
+// allowed[msg.sender][_spender] = _amount;
+// Approval(msg.sender, _spender, _amount);
+// return true;
+// }
+
+// /// @dev This function makes it easy to read the `allowed[]` map
+// /// @param _owner The address of the account that owns the token
+// /// @param _spender The address of the account able to transfer the tokens
+// /// @return Amount of remaining tokens of _owner that _spender is allowed
+// /// to spend
+// function allowance(address _owner, address _spender
+// ) constant returns (uint256 remaining) {
+// return allowed[_owner][_spender];
+// }
+
+// /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
+// /// its behalf, and then a function is triggered in the contract that is
+// /// being approved, `_spender`. This allows users to use their tokens to
+// /// interact with contracts in one function call instead of two
+// /// @param _spender The address of the contract able to transfer the tokens
+// /// @param _amount The amount of tokens to be approved for transfer
+// /// @return True if the function call was successful
+// function approveAndCall(address _spender, uint256 _amount, bytes _extraData
+// ) returns (bool success) {
+// if (!approve(_spender, _amount)) throw;
+
+// ApproveAndCallFallBack(_spender).receiveApproval(
+// msg.sender,
+// _amount,
+// this,
+// _extraData
+// );
+
+// return true;
+// }
+
+// /// @dev This function makes it easy to get the total number of tokens
+// /// @return The total number of tokens
+// function totalSupply() constant returns (uint) {
+// return totalSupplyAt(getBlockNumber());
+// }
+
+
+// ////////////////
+// // Query balance and totalSupply in History
+// ////////////////
+
+// /// @dev Queries the balance of `_owner` at a specific `_blockNumber`
+// /// @param _owner The address from which the balance will be retrieved
+// /// @param _blockNumber The block number when the balance is queried
+// /// @return The balance at `_blockNumber`
+// function balanceOfAt(address _owner, uint _blockNumber) constant
+// returns (uint) {
+
+// // These next few lines are used when the balance of the token is
+// // requested before a check point was ever created for this token, it
+// // requires that the `parentToken.balanceOfAt` be queried at the
+// // genesis block for that token as this contains initial balance of
+// // this token
+// if ((balances[_owner].length == 0)
+// || (balances[_owner][0].fromBlock > _blockNumber)) {
+// if (address(parentToken) != 0) {
+// return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock));
+// } else {
+// // Has no parent
+// return 0;
+// }
+
+// // This will return the expected balance during normal situations
+// } else {
+// return getValueAt(balances[_owner], _blockNumber);
+// }
+// }
+
+// /// @notice Total amount of tokens at a specific `_blockNumber`.
+// /// @param _blockNumber The block number when the totalSupply is queried
+// /// @return The total amount of tokens at `_blockNumber`
+// function totalSupplyAt(uint _blockNumber) constant returns(uint) {
+
+// // These next few lines are used when the totalSupply of the token is
+// // requested before a check point was ever created for this token, it
+// // requires that the `parentToken.totalSupplyAt` be queried at the
+// // genesis block for this token as that contains totalSupply of this
+// // token at this block number.
+// if ((totalSupplyHistory.length == 0)
+// || (totalSupplyHistory[0].fromBlock > _blockNumber)) {
+// if (address(parentToken) != 0) {
+// return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock));
+// } else {
+// return 0;
+// }
+
+// // This will return the expected totalSupply during normal situations
+// } else {
+// return getValueAt(totalSupplyHistory, _blockNumber);
+// }
+// }
+
+// ////////////////
+// // Clone Token Method
+// ////////////////
+
+// /// @notice Creates a new clone token with the initial distribution being
+// /// this token at `_snapshotBlock`
+// /// @param _cloneTokenName Name of the clone token
+// /// @param _cloneDecimalUnits Number of decimals of the smallest unit
+// /// @param _cloneTokenSymbol Symbol of the clone token
+// /// @param _snapshotBlock Block when the distribution of the parent token is
+// /// copied to set the initial distribution of the new clone token;
+// /// if the block is zero than the actual block, the current block is used
+// /// @param _transfersEnabled True if transfers are allowed in the clone
+// /// @return The address of the new MiniMeToken Contract
+// function createCloneToken(
+// string _cloneTokenName,
+// uint8 _cloneDecimalUnits,
+// string _cloneTokenSymbol,
+// uint _snapshotBlock,
+// bool _transfersEnabled
+// ) returns(address) {
+// if (_snapshotBlock == 0) _snapshotBlock = getBlockNumber();
+// MiniMeToken cloneToken = tokenFactory.createCloneToken(
+// this,
+// _snapshotBlock,
+// _cloneTokenName,
+// _cloneDecimalUnits,
+// _cloneTokenSymbol,
+// _transfersEnabled
+// );
+
+// cloneToken.changeController(msg.sender);
+
+// // An event to make the token easy to find on the blockchain
+// NewCloneToken(address(cloneToken), _snapshotBlock);
+// return address(cloneToken);
+// }
+
+// ////////////////
+// // Generate and destroy tokens
+// ////////////////
+
+// /// @notice Generates `_amount` tokens that are assigned to `_owner`
+// /// @param _owner The address that will be assigned the new tokens
+// /// @param _amount The quantity of tokens generated
+// /// @return True if the tokens are generated correctly
+// function generateTokens(address _owner, uint _amount
+// ) onlyController returns (bool) {
+// uint curTotalSupply = getValueAt(totalSupplyHistory, getBlockNumber());
+// if (curTotalSupply + _amount < curTotalSupply) throw; // Check for overflow
+// updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
+// var previousBalanceTo = balanceOf(_owner);
+// if (previousBalanceTo + _amount < previousBalanceTo) throw; // Check for overflow
+// updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
+// Transfer(0, _owner, _amount);
+// return true;
+// }
+
+
+// /// @notice Burns `_amount` tokens from `_owner`
+// /// @param _owner The address that will lose the tokens
+// /// @param _amount The quantity of tokens to burn
+// /// @return True if the tokens are burned correctly
+// function destroyTokens(address _owner, uint _amount
+// ) onlyController returns (bool) {
+// uint curTotalSupply = getValueAt(totalSupplyHistory, getBlockNumber());
+// if (curTotalSupply < _amount) throw;
+// updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
+// var previousBalanceFrom = balanceOf(_owner);
+// if (previousBalanceFrom < _amount) throw;
+// updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
+// Transfer(_owner, 0, _amount);
+// return true;
+// }
+
+// ////////////////
+// // Enable tokens transfers
+// ////////////////
+
+
+// /// @notice Enables token holders to transfer their tokens freely if true
+// /// @param _transfersEnabled True if transfers are allowed in the clone
+// function enableTransfers(bool _transfersEnabled) onlyController {
+// transfersEnabled = _transfersEnabled;
+// }
+
+// ////////////////
+// // Internal helper functions to query and set a value in a snapshot array
+// ////////////////
+
+// /// @dev `getValueAt` retrieves the number of tokens at a given block number
+// /// @param checkpoints The history of values being queried
+// /// @param _block The block number to retrieve the value at
+// /// @return The number of tokens being queried
+// function getValueAt(Checkpoint[] storage checkpoints, uint _block
+// ) constant internal returns (uint) {
+// if (checkpoints.length == 0) return 0;
+
+// // Shortcut for the actual value
+// if (_block >= checkpoints[checkpoints.length-1].fromBlock)
+// return checkpoints[checkpoints.length-1].value;
+// if (_block < checkpoints[0].fromBlock) return 0;
+
+// // Binary search of the value in the array
+// uint min = 0;
+// uint max = checkpoints.length-1;
+// while (max > min) {
+// uint mid = (max + min + 1)/ 2;
+// if (checkpoints[mid].fromBlock<=_block) {
+// min = mid;
+// } else {
+// max = mid-1;
+// }
+// }
+// return checkpoints[min].value;
+// }
+
+// /// @dev `updateValueAtNow` used to update the `balances` map and the
+// /// `totalSupplyHistory`
+// /// @param checkpoints The history of data being updated
+// /// @param _value The new number of tokens
+// function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value
+// ) internal {
+// if ((checkpoints.length == 0)
+// || (checkpoints[checkpoints.length -1].fromBlock < getBlockNumber())) {
+// Checkpoint newCheckPoint = checkpoints[ checkpoints.length++ ];
+// newCheckPoint.fromBlock = uint128(getBlockNumber());
+// newCheckPoint.value = uint128(_value);
+// } else {
+// Checkpoint oldCheckPoint = checkpoints[checkpoints.length-1];
+// oldCheckPoint.value = uint128(_value);
+// }
+// }
+
+// /// @dev Internal function to determine if an address is a contract
+// /// @param _addr The address being queried
+// /// @return True if `_addr` is a contract
+// function isContract(address _addr) constant internal returns(bool) {
+// uint size;
+// if (_addr == 0) return false;
+// assembly {
+// size := extcodesize(_addr)
+// }
+// return size>0;
+// }
+
+// /// @dev Helper function to return a min betwen the two uints
+// function min(uint a, uint b) internal returns (uint) {
+// return a < b ? a : b;
+// }
+
+// /// @notice The fallback function: If the contract's controller has not been
+// /// set to 0, then the `proxyPayment` method is called which relays the
+// /// ether and creates tokens as described in the token controller contract
+// function () payable {
+// if (isContract(controller)) {
+// if (! TokenController(controller).proxyPayment.value(msg.value)(msg.sender))
+// throw;
+// } else {
+// throw;
+// }
+// }
+
+
+// //////////
+// // Testing specific methods
+// //////////
+
+// /// @notice This function is overridden by the test Mocks.
+// function getBlockNumber() internal constant returns (uint256) {
+// return block.number;
+// }
+
+// //////////
+// // Safety Methods
+// //////////
+
+// /// @notice This method can be used by the controller to extract mistakenly
+// /// sent tokens to this contract.
+// /// @param _token The address of the token contract that you want to recover
+// /// set to 0 in case you want to extract ether.
+// function claimTokens(address _token) onlyController {
+// if (_token == 0x0) {
+// controller.transfer(this.balance);
+// return;
+// }
+
+// ERC20Token token = ERC20Token(_token);
+// uint balance = token.balanceOf(this);
+// token.transfer(controller, balance);
+// ClaimedTokens(_token, controller, balance);
+// }
+
+// ////////////////
+// // Events
+// ////////////////
+
+// event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
+// event Transfer(address indexed _from, address indexed _to, uint256 _amount);
+// event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
+// event Approval(
+// address indexed _owner,
+// address indexed _spender,
+// uint256 _amount
+// );
+
+// }
+
+
+// ////////////////
+// // MiniMeTokenFactory
+// ////////////////
+
+// /// @dev This contract is used to generate clone contracts from a contract.
+// /// In solidity this is the way to create a contract from a contract of the
+// /// same class
+// contract MiniMeTokenFactory {
+
+// /// @notice Update the DApp by creating a new token with new functionalities
+// /// the msg.sender becomes the controller of this clone token
+// /// @param _parentToken Address of the token being cloned
+// /// @param _snapshotBlock Block of the parent token that will
+// /// determine the initial distribution of the clone token
+// /// @param _tokenName Name of the new token
+// /// @param _decimalUnits Number of decimals of the new token
+// /// @param _tokenSymbol Token Symbol for the new token
+// /// @param _transfersEnabled If true, tokens will be able to be transferred
+// /// @return The address of the new token contract
+// function createCloneToken(
+// address _parentToken,
+// uint _snapshotBlock,
+// string _tokenName,
+// uint8 _decimalUnits,
+// string _tokenSymbol,
+// bool _transfersEnabled
+// ) returns (MiniMeToken) {
+// MiniMeToken newToken = new MiniMeToken(
+// this,
+// _parentToken,
+// _snapshotBlock,
+// _tokenName,
+// _decimalUnits,
+// _tokenSymbol,
+// _transfersEnabled
+// );
+
+// newToken.changeController(msg.sender);
+// return newToken;
+// }
+// }
+
+
+// /*
+// Copyright 2017, Jarrad Hope (Status Research & Development GmbH)
+// */
+
+
+// contract SNT is MiniMeToken {
+// // @dev SNT constructor just parametrizes the MiniMeIrrevocableVestedToken constructor
+// function SNT(address _tokenFactory)
+// MiniMeToken(
+// _tokenFactory,
+// 0x0, // no parent token
+// 0, // no snapshot block number from parent
+// "Status Network Token", // Token name
+// 18, // Decimals
+// "SNT", // Symbol
+// true // Enable transfers
+// ) {}
+// }
+
+
+// /*
+// Copyright 2017, Jordi Baylina
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// /// @title StatusContribution Contract
+// /// @author Jordi Baylina
+// /// @dev This contract will be the SNT controller during the contribution period.
+// /// This contract will determine the rules during this period.
+// /// Final users will generally not interact directly with this contract. ETH will
+// /// be sent to the SNT token contract. The ETH is sent to this contract and from here,
+// /// ETH is sent to the contribution walled and SNTs are mined according to the defined
+// /// rules.
+
+
+// contract StatusContribution is Owned, TokenController {
+// using SafeMath for uint256;
+
+// uint256 constant public failSafeLimit = 300000 ether;
+// uint256 constant public maxGuaranteedLimit = 30000 ether;
+// uint256 constant public exchangeRate = 10000;
+// uint256 constant public maxGasPrice = 50000000000;
+// uint256 constant public maxCallFrequency = 100;
+
+// MiniMeToken public SGT;
+// MiniMeToken public SNT;
+// uint256 public startBlock;
+// uint256 public endBlock;
+
+// address public destEthDevs;
+
+// address public destTokensDevs;
+// address public destTokensReserve;
+// uint256 public maxSGTSupply;
+// address public destTokensSgt;
+// DynamicCeiling public dynamicCeiling;
+
+// address public sntController;
+
+// mapping (address => uint256) public guaranteedBuyersLimit;
+// mapping (address => uint256) public guaranteedBuyersBought;
+
+// uint256 public totalGuaranteedCollected;
+// uint256 public totalNormalCollected;
+
+// uint256 public finalizedBlock;
+// uint256 public finalizedTime;
+
+// mapping (address => uint256) public lastCallBlock;
+
+// bool public paused;
+
+// modifier initialized() {
+// require(address(SNT) != 0x0);
+// _;
+// }
+
+// modifier contributionOpen() {
+// require(getBlockNumber() >= startBlock &&
+// getBlockNumber() <= endBlock &&
+// finalizedBlock == 0 &&
+// address(SNT) != 0x0);
+// _;
+// }
+
+// modifier notPaused() {
+// require(!paused);
+// _;
+// }
+
+// function StatusContribution() {
+// paused = false;
+// }
+
+
+// /// @notice This method should be called by the owner before the contribution
+// /// period starts This initializes most of the parameters
+// /// @param _snt Address of the SNT token contract
+// /// @param _sntController Token controller for the SNT that will be transferred after
+// /// the contribution finalizes.
+// /// @param _startBlock Block when the contribution period starts
+// /// @param _endBlock The last block that the contribution period is active
+// /// @param _dynamicCeiling Address of the contract that controls the ceiling
+// /// @param _destEthDevs Destination address where the contribution ether is sent
+// /// @param _destTokensReserve Address where the tokens for the reserve are sent
+// /// @param _destTokensSgt Address of the exchanger SGT-SNT where the SNT are sent
+// /// to be distributed to the SGT holders.
+// /// @param _destTokensDevs Address where the tokens for the dev are sent
+// /// @param _sgt Address of the SGT token contract
+// /// @param _maxSGTSupply Quantity of SGT tokens that would represent 10% of status.
+// function initialize(
+// address _snt,
+// address _sntController,
+
+// uint256 _startBlock,
+// uint256 _endBlock,
+
+// address _dynamicCeiling,
+
+// address _destEthDevs,
+
+// address _destTokensReserve,
+// address _destTokensSgt,
+// address _destTokensDevs,
+
+// address _sgt,
+// uint256 _maxSGTSupply
+// ) public onlyOwner {
+// // Initialize only once
+// require(address(SNT) == 0x0);
+
+// SNT = MiniMeToken(_snt);
+// require(SNT.totalSupply() == 0);
+// require(SNT.controller() == address(this));
+// require(SNT.decimals() == 18); // Same amount of decimals as ETH
+
+// require(_sntController != 0x0);
+// sntController = _sntController;
+
+// require(_startBlock >= getBlockNumber());
+// require(_startBlock < _endBlock);
+// startBlock = _startBlock;
+// endBlock = _endBlock;
+
+// require(_dynamicCeiling != 0x0);
+// dynamicCeiling = DynamicCeiling(_dynamicCeiling);
+
+// require(_destEthDevs != 0x0);
+// destEthDevs = _destEthDevs;
+
+// require(_destTokensReserve != 0x0);
+// destTokensReserve = _destTokensReserve;
+
+// require(_destTokensSgt != 0x0);
+// destTokensSgt = _destTokensSgt;
+
+// require(_destTokensDevs != 0x0);
+// destTokensDevs = _destTokensDevs;
+
+// require(_sgt != 0x0);
+// SGT = MiniMeToken(_sgt);
+
+// require(_maxSGTSupply >= MiniMeToken(SGT).totalSupply());
+// maxSGTSupply = _maxSGTSupply;
+// }
+
+// /// @notice Sets the limit for a guaranteed address. All the guaranteed addresses
+// /// will be able to get SNTs during the contribution period with his own
+// /// specific limit.
+// /// This method should be called by the owner after the initialization
+// /// and before the contribution starts.
+// /// @param _th Guaranteed address
+// /// @param _limit Limit for the guaranteed address.
+// function setGuaranteedAddress(address _th, uint256 _limit) public initialized onlyOwner {
+// require(getBlockNumber() < startBlock);
+// require(_limit > 0 && _limit <= maxGuaranteedLimit);
+// guaranteedBuyersLimit[_th] = _limit;
+// GuaranteedAddress(_th, _limit);
+// }
+
+// /// @notice If anybody sends Ether directly to this contract, consider he is
+// /// getting SNTs.
+// function () public payable notPaused {
+// proxyPayment(msg.sender);
+// }
+
+
+// //////////
+// // MiniMe Controller functions
+// //////////
+
+// /// @notice This method will generally be called by the SNT token contract to
+// /// acquire SNTs. Or directly from third parties that want to acquire SNTs in
+// /// behalf of a token holder.
+// /// @param _th SNT holder where the SNTs will be minted.
+// function proxyPayment(address _th) public payable notPaused initialized contributionOpen returns (bool) {
+// require(_th != 0x0);
+// if (guaranteedBuyersLimit[_th] > 0) {
+// buyGuaranteed(_th);
+// } else {
+// buyNormal(_th);
+// }
+// return true;
+// }
+
+// function onTransfer(address, address, uint256) public returns (bool) {
+// return false;
+// }
+
+// function onApprove(address, address, uint256) public returns (bool) {
+// return false;
+// }
+
+// function buyNormal(address _th) internal {
+// require(tx.gasprice <= maxGasPrice);
+
+// // Antispam mechanism
+// address caller;
+// if (msg.sender == address(SNT)) {
+// caller = _th;
+// } else {
+// caller = msg.sender;
+// }
+
+// // Do not allow contracts to game the system
+// require(!isContract(caller));
+
+// require(getBlockNumber().sub(lastCallBlock[caller]) >= maxCallFrequency);
+// lastCallBlock[caller] = getBlockNumber();
+
+// uint256 toCollect = dynamicCeiling.toCollect(totalNormalCollected);
+
+// uint256 toFund;
+// if (msg.value <= toCollect) {
+// toFund = msg.value;
+// } else {
+// toFund = toCollect;
+// }
+
+// totalNormalCollected = totalNormalCollected.add(toFund);
+// doBuy(_th, toFund, false);
+// }
+
+// function buyGuaranteed(address _th) internal {
+// uint256 toCollect = guaranteedBuyersLimit[_th];
+
+// uint256 toFund;
+// if (guaranteedBuyersBought[_th].add(msg.value) > toCollect) {
+// toFund = toCollect.sub(guaranteedBuyersBought[_th]);
+// } else {
+// toFund = msg.value;
+// }
+
+// guaranteedBuyersBought[_th] = guaranteedBuyersBought[_th].add(toFund);
+// totalGuaranteedCollected = totalGuaranteedCollected.add(toFund);
+// doBuy(_th, toFund, true);
+// }
+
+// function doBuy(address _th, uint256 _toFund, bool _guaranteed) internal {
+// assert(msg.value >= _toFund); // Not needed, but double check.
+// assert(totalCollected() <= failSafeLimit);
+
+// if (_toFund > 0) {
+// uint256 tokensGenerated = _toFund.mul(exchangeRate);
+// assert(SNT.generateTokens(_th, tokensGenerated));
+// destEthDevs.transfer(_toFund);
+// NewSale(_th, _toFund, tokensGenerated, _guaranteed);
+// }
+
+// uint256 toReturn = msg.value.sub(_toFund);
+// if (toReturn > 0) {
+// // If the call comes from the Token controller,
+// // then we return it to the token Holder.
+// // Otherwise we return to the sender.
+// if (msg.sender == address(SNT)) {
+// _th.transfer(toReturn);
+// } else {
+// msg.sender.transfer(toReturn);
+// }
+// }
+// }
+
+// // NOTE on Percentage format
+// // Right now, Solidity does not support decimal numbers. (This will change very soon)
+// // So in this contract we use a representation of a percentage that consist in
+// // expressing the percentage in "x per 10**18"
+// // This format has a precision of 16 digits for a percent.
+// // Examples:
+// // 3% = 3*(10**16)
+// // 100% = 100*(10**16) = 10**18
+// //
+// // To get a percentage of a value we do it by first multiplying it by the percentage in (x per 10^18)
+// // and then divide it by 10**18
+// //
+// // Y * X(in x per 10**18)
+// // X% of Y = -------------------------
+// // 100(in x per 10**18)
+// //
+
+
+// /// @notice This method will can be called by the owner before the contribution period
+// /// end or by anybody after the `endBlock`. This method finalizes the contribution period
+// /// by creating the remaining tokens and transferring the controller to the configured
+// /// controller.
+// function finalize() public initialized {
+// require(getBlockNumber() >= startBlock);
+// require(msg.sender == owner || getBlockNumber() > endBlock);
+// require(finalizedBlock == 0);
+
+// // Do not allow termination until all curves revealed.
+// require(dynamicCeiling.allRevealed());
+
+// // Allow premature finalization if final limit is reached
+// if (getBlockNumber() <= endBlock) {
+// var (,lastLimit,,) = dynamicCeiling.curves(dynamicCeiling.revealedCurves().sub(1));
+// require(totalNormalCollected >= lastLimit);
+// }
+
+// finalizedBlock = getBlockNumber();
+// finalizedTime = now;
+
+// uint256 percentageToSgt;
+// if (SGT.totalSupply() >= maxSGTSupply) {
+// percentageToSgt = percent(10); // 10%
+// } else {
+
+// //
+// // SGT.totalSupply()
+// // percentageToSgt = 10% * -------------------
+// // maxSGTSupply
+// //
+// percentageToSgt = percent(10).mul(SGT.totalSupply()).div(maxSGTSupply);
+// }
+
+// uint256 percentageToDevs = percent(20); // 20%
+
+
+// //
+// // % To Contributors = 41% + (10% - % to SGT holders)
+// //
+// uint256 percentageToContributors = percent(41).add(percent(10).sub(percentageToSgt));
+
+// uint256 percentageToReserve = percent(29);
+
+
+// // SNT.totalSupply() -> Tokens minted during the contribution
+// // totalTokens -> Total tokens that should be after the allocation
+// // of devTokens, sgtTokens and reserve
+// // percentageToContributors -> Which percentage should go to the
+// // contribution participants
+// // (x per 10**18 format)
+// // percent(100) -> 100% in (x per 10**18 format)
+// //
+// // percentageToContributors
+// // SNT.totalSupply() = -------------------------- * totalTokens =>
+// // percent(100)
+// //
+// //
+// // percent(100)
+// // => totalTokens = ---------------------------- * SNT.totalSupply()
+// // percentageToContributors
+// //
+// uint256 totalTokens = SNT.totalSupply().mul(percent(100)).div(percentageToContributors);
+
+
+// // Generate tokens for SGT Holders.
+
+// //
+// // percentageToReserve
+// // reserveTokens = ----------------------- * totalTokens
+// // percentage(100)
+// //
+// assert(SNT.generateTokens(
+// destTokensReserve,
+// totalTokens.mul(percentageToReserve).div(percent(100))));
+
+// //
+// // percentageToSgt
+// // sgtTokens = ----------------------- * totalTokens
+// // percentage(100)
+// //
+// assert(SNT.generateTokens(
+// destTokensSgt,
+// totalTokens.mul(percentageToSgt).div(percent(100))));
+
+
+// //
+// // percentageToDevs
+// // devTokens = ----------------------- * totalTokens
+// // percentage(100)
+// //
+// assert(SNT.generateTokens(
+// destTokensDevs,
+// totalTokens.mul(percentageToDevs).div(percent(100))));
+
+// SNT.changeController(sntController);
+
+// Finalized();
+// }
+
+// function percent(uint256 p) internal returns (uint256) {
+// return p.mul(10**16);
+// }
+
+// /// @dev Internal function to determine if an address is a contract
+// /// @param _addr The address being queried
+// /// @return True if `_addr` is a contract
+// function isContract(address _addr) constant internal returns (bool) {
+// if (_addr == 0) return false;
+// uint256 size;
+// assembly {
+// size := extcodesize(_addr)
+// }
+// return (size > 0);
+// }
+
+
+// //////////
+// // Constant functions
+// //////////
+
+// /// @return Total tokens issued in weis.
+// function tokensIssued() public constant returns (uint256) {
+// return SNT.totalSupply();
+// }
+
+// /// @return Total Ether collected.
+// function totalCollected() public constant returns (uint256) {
+// return totalNormalCollected.add(totalGuaranteedCollected);
+// }
+
+
+// //////////
+// // Testing specific methods
+// //////////
+
+// /// @notice This function is overridden by the test Mocks.
+// function getBlockNumber() internal constant returns (uint256) {
+// return block.number;
+// }
+
+
+// //////////
+// // Safety Methods
+// //////////
+
+// /// @notice This method can be used by the controller to extract mistakenly
+// /// sent tokens to this contract.
+// /// @param _token The address of the token contract that you want to recover
+// /// set to 0 in case you want to extract ether.
+// function claimTokens(address _token) public onlyOwner {
+// if (SNT.controller() == address(this)) {
+// SNT.claimTokens(_token);
+// }
+// if (_token == 0x0) {
+// owner.transfer(this.balance);
+// return;
+// }
+
+// ERC20Token token = ERC20Token(_token);
+// uint256 balance = token.balanceOf(this);
+// token.transfer(owner, balance);
+// ClaimedTokens(_token, owner, balance);
+// }
+
+
+// /// @notice Pauses the contribution if there is any issue
+// function pauseContribution() onlyOwner {
+// paused = true;
+// }
+
+// /// @notice Resumes the contribution
+// function resumeContribution() onlyOwner {
+// paused = false;
+// }
+
+// event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
+// event NewSale(address indexed _th, uint256 _amount, uint256 _tokens, bool _guaranteed);
+// event GuaranteedAddress(address indexed _th, uint256 _limit);
+// event Finalized();
+// }
+
+
+// /*
+// Copyright 2017, Jordi Baylina
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// /// @title ContributionWallet Contract
+// /// @author Jordi Baylina
+// /// @dev This contract will be hold the Ether during the contribution period.
+// /// The idea of this contract is to avoid recycling Ether during the contribution
+// /// period. So all the ETH collected will be locked here until the contribution
+// /// period ends
+
+// // @dev Contract to hold sale raised funds during the sale period.
+// // Prevents attack in which the Aragon Multisig sends raised ether
+// // to the sale contract to mint tokens to itself, and getting the
+// // funds back immediately.
+
+
+
+// contract ContributionWallet {
+
+// // Public variables
+// address public multisig;
+// uint256 public endBlock;
+// StatusContribution public contribution;
+
+// // @dev Constructor initializes public variables
+// // @param _multisig The address of the multisig that will receive the funds
+// // @param _endBlock Block after which the multisig can request the funds
+// // @param _contribution Address of the StatusContribution contract
+// function ContributionWallet(address _multisig, uint256 _endBlock, address _contribution) {
+// require(_multisig != 0x0);
+// require(_contribution != 0x0);
+// require(_endBlock != 0 && _endBlock <= 4000000);
+// multisig = _multisig;
+// endBlock = _endBlock;
+// contribution = StatusContribution(_contribution);
+// }
+
+// // @dev Receive all sent funds without any further logic
+// function () public payable {}
+
+// // @dev Withdraw function sends all the funds to the wallet if conditions are correct
+// function withdraw() public {
+// require(msg.sender == multisig); // Only the multisig can request it
+// require(block.number > endBlock || // Allow after end block
+// contribution.finalizedBlock() != 0); // Allow when sale is finalized
+// multisig.transfer(this.balance);
+// }
+
+// }
+
+
+// /*
+// Copyright 2017, Jordi Baylina
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-/// @title DevTokensHolder Contract
-/// @author Jordi Baylina
-/// @dev This contract will hold the tokens of the developers.
-/// Tokens will not be able to be collected until 6 months after the contribution
-/// period ends. And it will be increasing linearly until 2 years.
+// /// @title DevTokensHolder Contract
+// /// @author Jordi Baylina
+// /// @dev This contract will hold the tokens of the developers.
+// /// Tokens will not be able to be collected until 6 months after the contribution
+// /// period ends. And it will be increasing linearly until 2 years.
-// collectable tokens
-// | _/-------- vestedTokens rect
-// | _/
-// | _/
-// | _/
-// | _/
-// | _/
-// | _/
-// | _/
-// | |
-// | . |
-// | . |
-// | . |
-// +===+======+--------------+----------> time
-// Contrib 6 Months 24 Months
-// End
-
-
-
-contract DevTokensHolder is Owned {
- using SafeMath for uint256;
-
- uint256 collectedTokens;
- StatusContribution contribution;
- MiniMeToken snt;
-
- function DevTokensHolder(address _owner, address _contribution, address _snt) {
- owner = _owner;
- contribution = StatusContribution(_contribution);
- snt = MiniMeToken(_snt);
- }
-
-
- /// @notice The Dev (Owner) will call this method to extract the tokens
- function collectTokens() public onlyOwner {
- uint256 balance = snt.balanceOf(address(this));
- uint256 total = collectedTokens.add(balance);
-
- uint256 finalizedTime = contribution.finalizedTime();
-
- require(finalizedTime > 0 && getTime() > finalizedTime.add(months(6)));
-
- uint256 canExtract = total.mul(getTime().sub(finalizedTime)).div(months(24));
-
- canExtract = canExtract.sub(collectedTokens);
-
- if (canExtract > balance) {
- canExtract = balance;
- }
-
- collectedTokens = collectedTokens.add(canExtract);
- assert(snt.transfer(owner, canExtract));
+// // collectable tokens
+// // | _/-------- vestedTokens rect
+// // | _/
+// // | _/
+// // | _/
+// // | _/
+// // | _/
+// // | _/
+// // | _/
+// // | |
+// // | . |
+// // | . |
+// // | . |
+// // +===+======+--------------+----------> time
+// // Contrib 6 Months 24 Months
+// // End
+
+
+
+// contract DevTokensHolder is Owned {
+// using SafeMath for uint256;
+
+// uint256 collectedTokens;
+// StatusContribution contribution;
+// MiniMeToken snt;
+
+// function DevTokensHolder(address _owner, address _contribution, address _snt) {
+// owner = _owner;
+// contribution = StatusContribution(_contribution);
+// snt = MiniMeToken(_snt);
+// }
+
+
+// /// @notice The Dev (Owner) will call this method to extract the tokens
+// function collectTokens() public onlyOwner {
+// uint256 balance = snt.balanceOf(address(this));
+// uint256 total = collectedTokens.add(balance);
+
+// uint256 finalizedTime = contribution.finalizedTime();
+
+// require(finalizedTime > 0 && getTime() > finalizedTime.add(months(6)));
+
+// uint256 canExtract = total.mul(getTime().sub(finalizedTime)).div(months(24));
+
+// canExtract = canExtract.sub(collectedTokens);
+
+// if (canExtract > balance) {
+// canExtract = balance;
+// }
+
+// collectedTokens = collectedTokens.add(canExtract);
+// assert(snt.transfer(owner, canExtract));
- TokensWithdrawn(owner, canExtract);
- }
+// TokensWithdrawn(owner, canExtract);
+// }
- function months(uint256 m) internal returns (uint256) {
- return m.mul(30 days);
- }
+// function months(uint256 m) internal returns (uint256) {
+// return m.mul(30 days);
+// }
- function getTime() internal returns (uint256) {
- return now;
- }
+// function getTime() internal returns (uint256) {
+// return now;
+// }
- //////////
- // Safety Methods
- //////////
+// //////////
+// // Safety Methods
+// //////////
- /// @notice This method can be used by the controller to extract mistakenly
- /// sent tokens to this contract.
- /// @param _token The address of the token contract that you want to recover
- /// set to 0 in case you want to extract ether.
- function claimTokens(address _token) public onlyOwner {
- require(_token != address(snt));
- if (_token == 0x0) {
- owner.transfer(this.balance);
- return;
- }
+// /// @notice This method can be used by the controller to extract mistakenly
+// /// sent tokens to this contract.
+// /// @param _token The address of the token contract that you want to recover
+// /// set to 0 in case you want to extract ether.
+// function claimTokens(address _token) public onlyOwner {
+// require(_token != address(snt));
+// if (_token == 0x0) {
+// owner.transfer(this.balance);
+// return;
+// }
- ERC20Token token = ERC20Token(_token);
- uint256 balance = token.balanceOf(this);
- token.transfer(owner, balance);
- ClaimedTokens(_token, owner, balance);
- }
+// ERC20Token token = ERC20Token(_token);
+// uint256 balance = token.balanceOf(this);
+// token.transfer(owner, balance);
+// ClaimedTokens(_token, owner, balance);
+// }
- event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
- event TokensWithdrawn(address indexed _holder, uint256 _amount);
-}
+// event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
+// event TokensWithdrawn(address indexed _holder, uint256 _amount);
+// }
-/*
- Copyright 2017, Jordi Baylina
+// /*
+// Copyright 2017, Jordi Baylina
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- */
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-/// @title SGTExchanger Contract
-/// @author Jordi Baylina
-/// @dev This contract will be used to distribute SNT between SGT holders.
-/// SGT token is not transferable, and we just keep an accounting between all tokens
-/// deposited and the tokens collected.
-/// The controllerShip of SGT should be transferred to this contract before the
-/// contribution period starts.
+// /// @title SGTExchanger Contract
+// /// @author Jordi Baylina
+// /// @dev This contract will be used to distribute SNT between SGT holders.
+// /// SGT token is not transferable, and we just keep an accounting between all tokens
+// /// deposited and the tokens collected.
+// /// The controllerShip of SGT should be transferred to this contract before the
+// /// contribution period starts.
-contract SGTExchanger is TokenController, Owned {
- using SafeMath for uint256;
+// contract SGTExchanger is TokenController, Owned {
+// using SafeMath for uint256;
- mapping (address => uint256) public collected;
- uint256 public totalCollected;
- MiniMeToken public sgt;
- MiniMeToken public snt;
- StatusContribution public statusContribution;
+// mapping (address => uint256) public collected;
+// uint256 public totalCollected;
+// MiniMeToken public sgt;
+// MiniMeToken public snt;
+// StatusContribution public statusContribution;
- function SGTExchanger(address _sgt, address _snt, address _statusContribution) {
- sgt = MiniMeToken(_sgt);
- snt = MiniMeToken(_snt);
- statusContribution = StatusContribution(_statusContribution);
- }
+// function SGTExchanger(address _sgt, address _snt, address _statusContribution) {
+// sgt = MiniMeToken(_sgt);
+// snt = MiniMeToken(_snt);
+// statusContribution = StatusContribution(_statusContribution);
+// }
- /// @notice This method should be called by the SGT holders to collect their
- /// corresponding SNTs
- function collect() public {
- uint256 finalizedBlock = statusContribution.finalizedBlock();
+// /// @notice This method should be called by the SGT holders to collect their
+// /// corresponding SNTs
+// function collect() public {
+// uint256 finalizedBlock = statusContribution.finalizedBlock();
- require(finalizedBlock != 0);
- require(getBlockNumber() > finalizedBlock);
+// require(finalizedBlock != 0);
+// require(getBlockNumber() > finalizedBlock);
- uint256 total = totalCollected.add(snt.balanceOf(address(this)));
+// uint256 total = totalCollected.add(snt.balanceOf(address(this)));
- uint256 balance = sgt.balanceOfAt(msg.sender, finalizedBlock);
+// uint256 balance = sgt.balanceOfAt(msg.sender, finalizedBlock);
- // First calculate how much correspond to him
- uint256 amount = total.mul(balance).div(sgt.totalSupplyAt(finalizedBlock));
-
- // And then subtract the amount already collected
- amount = amount.sub(collected[msg.sender]);
-
- require(amount > 0); // Notify the user that there are no tokens to exchange
-
- totalCollected = totalCollected.add(amount);
- collected[msg.sender] = collected[msg.sender].add(amount);
-
- assert(snt.transfer(msg.sender, amount));
-
- TokensCollected(msg.sender, amount);
- }
-
- function proxyPayment(address) public payable returns (bool) {
- throw;
- }
-
- function onTransfer(address, address, uint256) public returns (bool) {
- return false;
- }
-
- function onApprove(address, address, uint256) public returns (bool) {
- return false;
- }
-
- //////////
- // Testing specific methods
- //////////
-
- /// @notice This function is overridden by the test Mocks.
- function getBlockNumber() internal constant returns (uint256) {
- return block.number;
- }
-
- //////////
- // Safety Method
- //////////
-
- /// @notice This method can be used by the controller to extract mistakenly
- /// sent tokens to this contract.
- /// @param _token The address of the token contract that you want to recover
- /// set to 0 in case you want to extract ether.
- function claimTokens(address _token) public onlyOwner {
- require(_token != address(snt));
- if (_token == 0x0) {
- owner.transfer(this.balance);
- return;
- }
-
- ERC20Token token = ERC20Token(_token);
- uint256 balance = token.balanceOf(this);
- token.transfer(owner, balance);
- ClaimedTokens(_token, owner, balance);
- }
-
- event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
- event TokensCollected(address indexed _holder, uint256 _amount);
-
-}
-
-/*
- Copyright 2017, Jordi Baylina
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- */
-
-/// @title SNTPlaceholder Contract
-/// @author Jordi Baylina
-/// @dev The SNTPlaceholder contract will take control over the SNT after the contribution
-/// is finalized and before the Status Network is deployed.
-/// The contract allows for SNT transfers and transferFrom and implements the
-/// logic for transferring control of the token to the network when the offering
-/// asks it to do so.
-
-
-contract SNTPlaceHolder is TokenController, Owned {
- using SafeMath for uint256;
-
- MiniMeToken public snt;
- StatusContribution public contribution;
- uint256 public activationTime;
- address public sgtExchanger;
-
- /// @notice Constructor
- /// @param _owner Trusted owner for this contract.
- /// @param _snt SNT token contract address
- /// @param _contribution StatusContribution contract address
- /// @param _sgtExchanger SGT-SNT Exchange address. (During the first week
- /// only this exchanger will be able to move tokens)
- function SNTPlaceHolder(address _owner, address _snt, address _contribution, address _sgtExchanger) {
- owner = _owner;
- snt = MiniMeToken(_snt);
- contribution = StatusContribution(_contribution);
- sgtExchanger = _sgtExchanger;
- }
-
- /// @notice The owner of this contract can change the controller of the SNT token
- /// Please, be sure that the owner is a trusted agent or 0x0 address.
- /// @param _newController The address of the new controller
-
- function changeController(address _newController) public onlyOwner {
- snt.changeController(_newController);
- ControllerChanged(_newController);
- }
-
-
- //////////
- // MiniMe Controller Interface functions
- //////////
-
- // In between the offering and the network. Default settings for allowing token transfers.
- function proxyPayment(address) public payable returns (bool) {
- return false;
- }
-
- function onTransfer(address _from, address, uint256) public returns (bool) {
- return transferable(_from);
- }
-
- function onApprove(address _from, address, uint256) public returns (bool) {
- return transferable(_from);
- }
-
- function transferable(address _from) internal returns (bool) {
- // Allow the exchanger to work from the beginning
- if (activationTime == 0) {
- uint256 f = contribution.finalizedTime();
- if (f > 0) {
- activationTime = f.add(1 weeks);
- } else {
- return false;
- }
- }
- return (getTime() > activationTime) || (_from == sgtExchanger);
- }
-
-
- //////////
- // Testing specific methods
- //////////
-
- /// @notice This function is overrided by the test Mocks.
- function getTime() internal returns (uint256) {
- return now;
- }
-
-
- //////////
- // Safety Methods
- //////////
-
- /// @notice This method can be used by the controller to extract mistakenly
- /// sent tokens to this contract.
- /// @param _token The address of the token contract that you want to recover
- /// set to 0 in case you want to extract ether.
- function claimTokens(address _token) public onlyOwner {
- if (snt.controller() == address(this)) {
- snt.claimTokens(_token);
- }
- if (_token == 0x0) {
- owner.transfer(this.balance);
- return;
- }
-
- ERC20Token token = ERC20Token(_token);
- uint256 balance = token.balanceOf(this);
- token.transfer(owner, balance);
- ClaimedTokens(_token, owner, balance);
- }
-
- event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
- event ControllerChanged(address indexed _newController);
-}
\ No newline at end of file
+// // First calculate how much correspond to him
+// uint256 amount = total.mul(balance).div(sgt.totalSupplyAt(finalizedBlock));
+
+// // And then subtract the amount already collected
+// amount = amount.sub(collected[msg.sender]);
+
+// require(amount > 0); // Notify the user that there are no tokens to exchange
+
+// totalCollected = totalCollected.add(amount);
+// collected[msg.sender] = collected[msg.sender].add(amount);
+
+// assert(snt.transfer(msg.sender, amount));
+
+// TokensCollected(msg.sender, amount);
+// }
+
+// function proxyPayment(address) public payable returns (bool) {
+// throw;
+// }
+
+// function onTransfer(address, address, uint256) public returns (bool) {
+// return false;
+// }
+
+// function onApprove(address, address, uint256) public returns (bool) {
+// return false;
+// }
+
+// //////////
+// // Testing specific methods
+// //////////
+
+// /// @notice This function is overridden by the test Mocks.
+// function getBlockNumber() internal constant returns (uint256) {
+// return block.number;
+// }
+
+// //////////
+// // Safety Method
+// //////////
+
+// /// @notice This method can be used by the controller to extract mistakenly
+// /// sent tokens to this contract.
+// /// @param _token The address of the token contract that you want to recover
+// /// set to 0 in case you want to extract ether.
+// function claimTokens(address _token) public onlyOwner {
+// require(_token != address(snt));
+// if (_token == 0x0) {
+// owner.transfer(this.balance);
+// return;
+// }
+
+// ERC20Token token = ERC20Token(_token);
+// uint256 balance = token.balanceOf(this);
+// token.transfer(owner, balance);
+// ClaimedTokens(_token, owner, balance);
+// }
+
+// event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
+// event TokensCollected(address indexed _holder, uint256 _amount);
+
+// }
+
+// /*
+// Copyright 2017, Jordi Baylina
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// /// @title SNTPlaceholder Contract
+// /// @author Jordi Baylina
+// /// @dev The SNTPlaceholder contract will take control over the SNT after the contribution
+// /// is finalized and before the Status Network is deployed.
+// /// The contract allows for SNT transfers and transferFrom and implements the
+// /// logic for transferring control of the token to the network when the offering
+// /// asks it to do so.
+
+
+// contract SNTPlaceHolder is TokenController, Owned {
+// using SafeMath for uint256;
+
+// MiniMeToken public snt;
+// StatusContribution public contribution;
+// uint256 public activationTime;
+// address public sgtExchanger;
+
+// /// @notice Constructor
+// /// @param _owner Trusted owner for this contract.
+// /// @param _snt SNT token contract address
+// /// @param _contribution StatusContribution contract address
+// /// @param _sgtExchanger SGT-SNT Exchange address. (During the first week
+// /// only this exchanger will be able to move tokens)
+// function SNTPlaceHolder(address _owner, address _snt, address _contribution, address _sgtExchanger) {
+// owner = _owner;
+// snt = MiniMeToken(_snt);
+// contribution = StatusContribution(_contribution);
+// sgtExchanger = _sgtExchanger;
+// }
+
+// /// @notice The owner of this contract can change the controller of the SNT token
+// /// Please, be sure that the owner is a trusted agent or 0x0 address.
+// /// @param _newController The address of the new controller
+
+// function changeController(address _newController) public onlyOwner {
+// snt.changeController(_newController);
+// ControllerChanged(_newController);
+// }
+
+
+// //////////
+// // MiniMe Controller Interface functions
+// //////////
+
+// // In between the offering and the network. Default settings for allowing token transfers.
+// function proxyPayment(address) public payable returns (bool) {
+// return false;
+// }
+
+// function onTransfer(address _from, address, uint256) public returns (bool) {
+// return transferable(_from);
+// }
+
+// function onApprove(address _from, address, uint256) public returns (bool) {
+// return transferable(_from);
+// }
+
+// function transferable(address _from) internal returns (bool) {
+// // Allow the exchanger to work from the beginning
+// if (activationTime == 0) {
+// uint256 f = contribution.finalizedTime();
+// if (f > 0) {
+// activationTime = f.add(1 weeks);
+// } else {
+// return false;
+// }
+// }
+// return (getTime() > activationTime) || (_from == sgtExchanger);
+// }
+
+
+// //////////
+// // Testing specific methods
+// //////////
+
+// /// @notice This function is overrided by the test Mocks.
+// function getTime() internal returns (uint256) {
+// return now;
+// }
+
+
+// //////////
+// // Safety Methods
+// //////////
+
+// /// @notice This method can be used by the controller to extract mistakenly
+// /// sent tokens to this contract.
+// /// @param _token The address of the token contract that you want to recover
+// /// set to 0 in case you want to extract ether.
+// function claimTokens(address _token) public onlyOwner {
+// if (snt.controller() == address(this)) {
+// snt.claimTokens(_token);
+// }
+// if (_token == 0x0) {
+// owner.transfer(this.balance);
+// return;
+// }
+
+// ERC20Token token = ERC20Token(_token);
+// uint256 balance = token.balanceOf(this);
+// token.transfer(owner, balance);
+// ClaimedTokens(_token, owner, balance);
+// }
+
+// event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
+// event ControllerChanged(address indexed _newController);
+// }
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index d269f8f..db30cad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,11 +1,15 @@
{
"name": "hardhat-project",
+ "version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "hardhat-project",
+ "version": "1.0.0",
+ "license": "ISC",
"dependencies": {
+ "@openzeppelin/contracts": "^3.4.2-solc-0.7",
"dotenv": "^16.0.1"
},
"devDependencies": {
@@ -16,7 +20,7 @@
"chai": "^4.3.6",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.6.9",
- "hardhat": "^2.9.9",
+ "hardhat": "^2.10.1",
"hardhat-gas-reporter": "^1.0.8",
"solidity-coverage": "^0.7.21",
"ts-node": "^10.8.1",
@@ -1355,6 +1359,11 @@
"hardhat": "^2.0.0"
}
},
+ "node_modules/@openzeppelin/contracts": {
+ "version": "3.4.2-solc-0.7",
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-3.4.2-solc-0.7.tgz",
+ "integrity": "sha512-W6QmqgkADuFcTLzHL8vVoNBtkwjvQRpYIAom7KiUNoLKghyx3FgH0GBjt8NRvigV1ZmMOBllvE1By1C+bi8WpA=="
+ },
"node_modules/@resolver-engine/core": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz",
@@ -14630,9 +14639,9 @@
}
},
"node_modules/hardhat": {
- "version": "2.9.9",
- "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.9.9.tgz",
- "integrity": "sha512-Qv7SXnRc0zq1kGXruNnSKpP3eFccXMR5Qv6GVX9hBIJ5efN0PflKPq92aQ5Cv3jrjJeRevLznWZVz7bttXhVfw==",
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.10.1.tgz",
+ "integrity": "sha512-0FN9TyCtn7Lt25SB2ei2G7nA2rZjP+RN6MvFOm+zYwherxLZNo6RbD8nDz88eCbhRapevmXqOiL2nM8INKsjmA==",
"dev": true,
"dependencies": {
"@ethereumjs/block": "^3.6.2",
@@ -14643,7 +14652,7 @@
"@ethersproject/abi": "^5.1.2",
"@metamask/eth-sig-util": "^4.0.0",
"@sentry/node": "^5.18.1",
- "@solidity-parser/parser": "^0.14.1",
+ "@solidity-parser/parser": "^0.14.2",
"@types/bn.js": "^5.1.0",
"@types/lru-cache": "^5.1.0",
"abort-controller": "^3.0.0",
@@ -14656,7 +14665,7 @@
"debug": "^4.1.1",
"enquirer": "^2.3.0",
"env-paths": "^2.2.0",
- "ethereum-cryptography": "^0.1.2",
+ "ethereum-cryptography": "^1.0.3",
"ethereumjs-abi": "^0.6.8",
"ethereumjs-util": "^7.1.4",
"find-up": "^2.1.0",
@@ -14668,7 +14677,7 @@
"lodash": "^4.17.11",
"merkle-patricia-tree": "^4.2.4",
"mnemonist": "^0.38.0",
- "mocha": "^9.2.0",
+ "mocha": "^10.0.0",
"p-map": "^4.0.0",
"qs": "^6.7.0",
"raw-body": "^2.4.1",
@@ -14688,7 +14697,7 @@
"hardhat": "internal/cli/cli.js"
},
"engines": {
- "node": "^12.0.0 || ^14.0.0 || ^16.0.0"
+ "node": "^14.0.0 || ^16.0.0 || ^18.0.0"
},
"peerDependencies": {
"ts-node": "*",
@@ -14717,6 +14726,42 @@
"hardhat": "^2.0.2"
}
},
+ "node_modules/hardhat/node_modules/@noble/hashes": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz",
+ "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
+ "node_modules/hardhat/node_modules/@noble/secp256k1": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz",
+ "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
+ "node_modules/hardhat/node_modules/ethereum-cryptography": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz",
+ "integrity": "sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==",
+ "dev": true,
+ "dependencies": {
+ "@noble/hashes": "1.1.2",
+ "@noble/secp256k1": "1.6.3",
+ "@scure/bip32": "1.1.0",
+ "@scure/bip39": "1.1.0"
+ }
+ },
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@@ -16261,42 +16306,40 @@
}
},
"node_modules/mocha": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz",
- "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz",
+ "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==",
"dev": true,
"dependencies": {
"@ungap/promise-all-settled": "1.1.2",
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
"chokidar": "3.5.3",
- "debug": "4.3.3",
+ "debug": "4.3.4",
"diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
"glob": "7.2.0",
- "growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "4.1.0",
"log-symbols": "4.1.0",
- "minimatch": "4.2.1",
+ "minimatch": "5.0.1",
"ms": "2.1.3",
- "nanoid": "3.3.1",
+ "nanoid": "3.3.3",
"serialize-javascript": "6.0.0",
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
- "which": "2.0.2",
- "workerpool": "6.2.0",
+ "workerpool": "6.2.1",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
"yargs-unparser": "2.0.0"
},
"bin": {
"_mocha": "bin/_mocha",
- "mocha": "bin/mocha"
+ "mocha": "bin/mocha.js"
},
"engines": {
- "node": ">= 12.0.0"
+ "node": ">= 14.0.0"
},
"funding": {
"type": "opencollective",
@@ -16312,29 +16355,15 @@
"node": ">=6"
}
},
- "node_modules/mocha/node_modules/debug": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
- "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "node_modules/mocha/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "balanced-match": "^1.0.0"
}
},
- "node_modules/mocha/node_modules/debug/node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
"node_modules/mocha/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -16388,12 +16417,12 @@
}
},
"node_modules/mocha/node_modules/minimatch": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
- "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
"dev": true,
"dependencies": {
- "brace-expansion": "^1.1.7"
+ "brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
@@ -16521,9 +16550,9 @@
"dev": true
},
"node_modules/nanoid": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
- "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
"dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
@@ -20291,21 +20320,6 @@
"webidl-conversions": "^3.0.0"
}
},
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/which-boxed-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
@@ -20428,9 +20442,9 @@
"dev": true
},
"node_modules/workerpool": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz",
- "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
"dev": true
},
"node_modules/wrap-ansi": {
@@ -21590,6 +21604,11 @@
"@types/web3": "1.0.19"
}
},
+ "@openzeppelin/contracts": {
+ "version": "3.4.2-solc-0.7",
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-3.4.2-solc-0.7.tgz",
+ "integrity": "sha512-W6QmqgkADuFcTLzHL8vVoNBtkwjvQRpYIAom7KiUNoLKghyx3FgH0GBjt8NRvigV1ZmMOBllvE1By1C+bi8WpA=="
+ },
"@resolver-engine/core": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz",
@@ -32052,9 +32071,9 @@
}
},
"hardhat": {
- "version": "2.9.9",
- "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.9.9.tgz",
- "integrity": "sha512-Qv7SXnRc0zq1kGXruNnSKpP3eFccXMR5Qv6GVX9hBIJ5efN0PflKPq92aQ5Cv3jrjJeRevLznWZVz7bttXhVfw==",
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.10.1.tgz",
+ "integrity": "sha512-0FN9TyCtn7Lt25SB2ei2G7nA2rZjP+RN6MvFOm+zYwherxLZNo6RbD8nDz88eCbhRapevmXqOiL2nM8INKsjmA==",
"dev": true,
"requires": {
"@ethereumjs/block": "^3.6.2",
@@ -32065,7 +32084,7 @@
"@ethersproject/abi": "^5.1.2",
"@metamask/eth-sig-util": "^4.0.0",
"@sentry/node": "^5.18.1",
- "@solidity-parser/parser": "^0.14.1",
+ "@solidity-parser/parser": "^0.14.2",
"@types/bn.js": "^5.1.0",
"@types/lru-cache": "^5.1.0",
"abort-controller": "^3.0.0",
@@ -32078,7 +32097,7 @@
"debug": "^4.1.1",
"enquirer": "^2.3.0",
"env-paths": "^2.2.0",
- "ethereum-cryptography": "^0.1.2",
+ "ethereum-cryptography": "^1.0.3",
"ethereumjs-abi": "^0.6.8",
"ethereumjs-util": "^7.1.4",
"find-up": "^2.1.0",
@@ -32090,7 +32109,7 @@
"lodash": "^4.17.11",
"merkle-patricia-tree": "^4.2.4",
"mnemonist": "^0.38.0",
- "mocha": "^9.2.0",
+ "mocha": "^10.0.0",
"p-map": "^4.0.0",
"qs": "^6.7.0",
"raw-body": "^2.4.1",
@@ -32105,6 +32124,32 @@
"undici": "^5.4.0",
"uuid": "^8.3.2",
"ws": "^7.4.6"
+ },
+ "dependencies": {
+ "@noble/hashes": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz",
+ "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==",
+ "dev": true
+ },
+ "@noble/secp256k1": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz",
+ "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==",
+ "dev": true
+ },
+ "ethereum-cryptography": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz",
+ "integrity": "sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==",
+ "dev": true,
+ "requires": {
+ "@noble/hashes": "1.1.2",
+ "@noble/secp256k1": "1.6.3",
+ "@scure/bip32": "1.1.0",
+ "@scure/bip39": "1.1.0"
+ }
+ }
}
},
"hardhat-gas-reporter": {
@@ -33299,32 +33344,30 @@
}
},
"mocha": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz",
- "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz",
+ "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==",
"dev": true,
"requires": {
"@ungap/promise-all-settled": "1.1.2",
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
"chokidar": "3.5.3",
- "debug": "4.3.3",
+ "debug": "4.3.4",
"diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
"glob": "7.2.0",
- "growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "4.1.0",
"log-symbols": "4.1.0",
- "minimatch": "4.2.1",
+ "minimatch": "5.0.1",
"ms": "2.1.3",
- "nanoid": "3.3.1",
+ "nanoid": "3.3.3",
"serialize-javascript": "6.0.0",
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
- "which": "2.0.2",
- "workerpool": "6.2.0",
+ "workerpool": "6.2.1",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
"yargs-unparser": "2.0.0"
@@ -33336,21 +33379,13 @@
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
"dev": true
},
- "debug": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
- "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"requires": {
- "ms": "2.1.2"
- },
- "dependencies": {
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- }
+ "balanced-match": "^1.0.0"
}
},
"escape-string-regexp": {
@@ -33385,12 +33420,12 @@
}
},
"minimatch": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
- "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
"dev": true,
"requires": {
- "brace-expansion": "^1.1.7"
+ "brace-expansion": "^2.0.1"
}
},
"ms": {
@@ -33495,9 +33530,9 @@
"dev": true
},
"nanoid": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
- "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
"dev": true
},
"negotiator": {
@@ -36548,15 +36583,6 @@
"webidl-conversions": "^3.0.0"
}
},
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
"which-boxed-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
@@ -36651,9 +36677,9 @@
"dev": true
},
"workerpool": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz",
- "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
"dev": true
},
"wrap-ansi": {
diff --git a/package.json b/package.json
index aa2e152..e5b68c7 100644
--- a/package.json
+++ b/package.json
@@ -8,13 +8,33 @@
"chai": "^4.3.6",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.6.9",
- "hardhat": "^2.9.9",
+ "hardhat": "^2.10.1",
"hardhat-gas-reporter": "^1.0.8",
"solidity-coverage": "^0.7.21",
"ts-node": "^10.8.1",
"typescript": "^4.7.4"
},
"dependencies": {
+ "@openzeppelin/contracts": "^3.4.2-solc-0.7",
"dotenv": "^16.0.1"
- }
+ },
+ "description": "This project demonstrates an advanced Hardhat use case, integrating other tools commonly used alongside Hardhat in the ecosystem.",
+ "version": "1.0.0",
+ "main": ".eslintrc.js",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vacp2p/rln-contract.git"
+ },
+ "author": "",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/vacp2p/rln-contract/issues"
+ },
+ "homepage": "https://github.com/vacp2p/rln-contract#readme"
}