diff --git a/contracts/Controlled.sol b/contracts/Controlled.sol
new file mode 100644
index 00000000..6e0d878f
--- /dev/null
+++ b/contracts/Controlled.sol
@@ -0,0 +1,30 @@
+pragma solidity ^0.4.13;
+
+import './ITokenController.sol';
+
+contract Controlled {
+
+ ITokenController public controller;
+
+ /// @notice The address of the controller is the only address that can call
+ /// a function with this modifier
+ modifier onlyController
+ {
+ require(msg.sender == address(controller));
+ _;
+ }
+
+ function Controlled()
+ {
+ controller = ITokenController(msg.sender);
+ }
+
+ /// @notice Changes the controller of the contract
+ /// @param _newController The new controller of the contract
+ function changeController(ITokenController _newController)
+ public
+ onlyController
+ {
+ controller = _newController;
+ }
+}
diff --git a/contracts/ControllerClaims.sol b/contracts/ControllerClaims.sol
new file mode 100644
index 00000000..cab6ebf2
--- /dev/null
+++ b/contracts/ControllerClaims.sol
@@ -0,0 +1,38 @@
+pragma solidity ^0.4.13;
+
+import './Controlled.sol';
+import './Standards/IBasicToken.sol';
+
+contract ControllerClaims is Controlled {
+
+////////////////
+// Events
+////////////////
+
+ event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
+
+ event ClaimedOwnership(address indexed _owned, address indexed _controller);
+
+///////////////////
+// Public functions
+///////////////////
+
+ /// @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(IBasicToken _token)
+ public
+ onlyController
+ {
+ // Transfer Ether
+ if (address(_token) == 0) {
+ controller.transfer(this.balance);
+ return;
+ }
+
+ uint balance = _token.balanceOf(this);
+ _token.transfer(controller, balance);
+ ClaimedTokens(_token, controller, balance);
+ }
+}
diff --git a/contracts/SampleCampaign-TokenController.sol b/contracts/Examples/SampleCampaign-TokenController.sol
similarity index 99%
rename from contracts/SampleCampaign-TokenController.sol
rename to contracts/Examples/SampleCampaign-TokenController.sol
index 890b8ca1..8d4f36d7 100644
--- a/contracts/SampleCampaign-TokenController.sol
+++ b/contracts/Examples/SampleCampaign-TokenController.sol
@@ -1,4 +1,4 @@
-pragma solidity ^0.4.6;
+pragma solidity ^0.4.13;
/*
Copyright 2017, Jordi Baylina
diff --git a/contracts/Extensions/Disbursal.sol b/contracts/Extensions/Disbursal.sol
new file mode 100644
index 00000000..75731de5
--- /dev/null
+++ b/contracts/Extensions/Disbursal.sol
@@ -0,0 +1,251 @@
+pragma solidity ^0.4.13;
+
+import '../Standards/ISnapshotToken.sol';
+import '../Standards/IBasicToken.sol';
+import '../Standards/IERC20Token.sol';
+import '../Standards/IApproveAndCallFallback.sol';
+
+// TODO: Anyone can create a token and disburse it, but then everyone
+// needs to pay extra gas for claim(). It is not possible to skip
+// these mallicious disbursals. Some solution strategies:
+// * Limit the people who can disburse to a trusted set
+// * Allow claims in any order
+
+contract Disbursal is IApproveAndCallFallback {
+
+////////////////
+// Types
+////////////////
+
+ struct Disbursment {
+ uint256 snapshot;
+ IBasicToken disbursedToken;
+ uint256 remainingAmount;
+ uint256 remainingShares;
+ }
+
+////////////////
+// State
+////////////////
+
+ ISnapshotToken public SHARE_TOKEN;
+
+ Disbursment[] disbursments;
+
+ mapping(address => mapping(uint256 => bool)) claimed;
+
+////////////////
+// Events
+////////////////
+
+ event Disbursed(
+ uint256 disbursalIndex,
+ IBasicToken disbursedToken,
+ uint256 amount,
+ uint256 snapshot,
+ uint256 totalShares
+ );
+
+ event Claimed(
+ address beneficiary,
+ uint256 disbursalIndex,
+ IBasicToken disbursedToken,
+ uint256 amount
+ );
+
+////////////////
+// Constructor
+////////////////
+
+ function Disbursal(
+ ISnapshotToken shareToken
+ )
+ public
+ {
+ SHARE_TOKEN = shareToken;
+ }
+
+////////////////
+// Public functions
+////////////////
+
+ function claimables(address beneficiary, uint256 from)
+ public
+ constant
+ returns (uint256[100])
+ {
+ uint256[100] memory result;
+ uint j = 0;
+ for (uint256 i = from; i < disbursments.length; ++i) {
+ if (claimable(beneficiary, i)) {
+ result[j] = i;
+ j += 1;
+ if (j == 100) {
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ function claimable(address beneficiary, uint256 index)
+ public
+ constant
+ returns (bool)
+ {
+ // Invalid index
+ if(index >= disbursments.length) {
+ return false;
+ }
+
+ // Already claimed
+ if(claimed[beneficiary][index] == true) {
+ return false;
+ }
+
+ // Check if `beneficiary` has shares
+ Disbursment storage disbursment = disbursments[index];
+ uint256 shares = SHARE_TOKEN.balanceOfAt(beneficiary, disbursment.snapshot);
+ return shares > 0;
+ }
+
+ function claim()
+ public
+ {
+ claim(msg.sender);
+ }
+
+ function claim(address beneficiary)
+ public
+ {
+ for(uint256 i = 0; i < disbursments.length; ++i) {
+ if(claimed[beneficiary][i] == false) {
+ claim(beneficiary, i);
+ }
+ }
+ }
+
+ function claim(address beneficiary, uint256[] indices)
+ public
+ {
+ for(uint256 i = 0; i < indices.length; ++i) {
+ claim(beneficiary, indices[i]);
+ }
+ }
+
+ function claim(address beneficiary, uint256 index)
+ public
+ {
+ require(index < disbursments.length);
+ require(claimed[beneficiary][index] == false);
+
+ // Compute share
+ // NOTE: By mainting both remaining counters we have automatic
+ // distribution of rounding errors between claims, with the
+ // final claim being exact and issuing all the remaining tokens.
+ // TODO: Remove < 2¹²⁸ restrictions
+ // TODO: Correct rounding instead of floor.
+ Disbursment storage disbursment = disbursments[index];
+ uint256 shares = SHARE_TOKEN.balanceOfAt(beneficiary, disbursment.snapshot);
+ assert(disbursment.remainingShares < 2**128);
+ assert(disbursment.remainingAmount < 2**128);
+ assert(shares <= disbursment.remainingShares);
+ uint256 amount = mulDiv(disbursment.remainingAmount, shares, disbursment.remainingShares);
+ assert(amount <= disbursment.remainingAmount);
+
+ // Update state
+ // TODO: Can we reduce the number of state writes?
+ disbursment.remainingAmount -= amount;
+ disbursment.remainingShares -= shares;
+ claimed[beneficiary][index] = true;
+
+ // Transfer tokens
+ IBasicToken token = disbursment.disbursedToken;
+ bool success = token.transfer(beneficiary, amount);
+ require(success);
+
+ // Log and return
+ Claimed(beneficiary, index, token, amount);
+ }
+
+ function disburseAllowance(IERC20Token token)
+ public
+ {
+ uint256 amount = token.allowance(msg.sender, this);
+ disburseAllowance(token, msg.sender, amount);
+ }
+
+ function disburseAllowance(IERC20Token token, address from, uint256 amount)
+ public
+ {
+ // Transfer all allowed tokens to self.
+ require(amount < 2**128);
+ bool success = token.transferFrom(from, this, amount);
+ require(success);
+
+ // Disburse these tokens
+ disburse(IBasicToken(token), amount);
+ }
+
+ // ERC20 receiver
+ function receiveApproval(address from, uint256 amount, IERC20Token token, bytes data)
+ public
+ {
+ require(data.length == 0);
+ disburseAllowance(token, from, amount);
+ }
+
+ // TODO: ERC223 style receiver
+
+////////////////
+// Internal functions
+////////////////
+
+ // TODO: Ideally we make this function public, and allow
+ // disbursal of any basic token. When counting how
+ // many tokens we need to disburse, a simple
+ // `balanceOf(this)` is insufficient, as it also
+ // contains the remaining amount from previous disbursments.
+ function disburse(IBasicToken token, uint256 amount)
+ internal
+ {
+ // Transfer all allowed tokens to self.
+ require(amount > 0);
+ require(amount < 2**128);
+
+ // Verify our balance
+ // TODO: we need to check for newly received tokens!
+
+ // Create snapshot
+ uint256 snapshot = SHARE_TOKEN.createSnapshot();
+ uint256 totalShares = SHARE_TOKEN.totalSupplyAt(snapshot);
+ require(totalShares < 2**128);
+
+ // Create disbursal
+ uint256 index = disbursments.length;
+ disbursments.push(Disbursment({
+ snapshot: snapshot,
+ disbursedToken: token,
+ remainingAmount: amount,
+ remainingShares: totalShares
+ }));
+
+ // Log
+ Disbursed(index, token, amount, snapshot, totalShares);
+ }
+
+ function mulDiv(
+ uint256 value,
+ uint256 numerator,
+ uint256 denominator
+ )
+ internal
+ constant
+ returns (uint256)
+ {
+ require(value < 2**128);
+ require(numerator < 2**128);
+ require(numerator <= denominator);
+ return (value * numerator) / denominator;
+ }
+}
diff --git a/contracts/Extensions/Vote.sol b/contracts/Extensions/Vote.sol
new file mode 100644
index 00000000..ca348531
--- /dev/null
+++ b/contracts/Extensions/Vote.sol
@@ -0,0 +1,59 @@
+pragma solidity ^0.4.13;
+
+import '../Standards/ISnapshotToken.sol';
+
+// https://en.wikipedia.org/wiki/Comparison_of_electoral_systems
+
+// https://en.wikipedia.org/wiki/Arrow%27s_impossibility_theorem
+// https://en.wikipedia.org/wiki/Gibbard%E2%80%93Satterthwaite_theorem
+
+// * Votes are public
+// * Voting is weighed by amount of tokens owned
+// * Votes can be changed
+// *
+
+// Cardinal systems are a natural fit for a token based voting system.
+// * https://en.wikipedia.org/wiki/Approval_voting
+// * https://en.wikipedia.org/wiki/Majority_judgment
+// → https://en.wikipedia.org/wiki/Range_voting
+
+// TODO: Implement Range voting with:
+// * Votes proportional to shares (i.e. one vote per share)
+// * Proxy voting: ability to delegate voting power
+// * Ability to trade voting power (is this the same as above?)
+
+// TODO:
+
+contract Vote {
+
+ ISnapshotToken public TOKEN;
+ uint256 public SNAPSHOT;
+ bytes32[] public CHOICE_HASHES;
+
+ string[] public choices;
+ uint256[] totals;
+
+ // Note: we use hashes because Solidity currently does not support passing
+ // string[] as an argument for external functions.
+ function Vote(
+ ISnapshotToken token,
+ bytes32[] choiceHashes
+ ) {
+ TOKEN = token;
+ SNAPSHOT = token.createSnapshot();
+ CHOICE_HASHES = choiceHashes;
+ choices.length = CHOICE_HASHES.length;
+ }
+
+ function initChoice(uint index, string choice)
+ {
+ require(index < CHOICE_HASHES.length);
+ require(keccak256(choice) == CHOICE_HASHES[index]);
+ choices[index] = choice;
+ }
+
+ function vote(uint256[] votes)
+ public
+ {
+ }
+}
diff --git a/contracts/Helpers/Allowance.sol b/contracts/Helpers/Allowance.sol
new file mode 100644
index 00000000..29afcc54
--- /dev/null
+++ b/contracts/Helpers/Allowance.sol
@@ -0,0 +1,117 @@
+pragma solidity ^0.4.13;
+
+import '../Standards/IERC20Allowance.sol';
+import '../Standards/IApproveAndCallFallback.sol';
+import './MAllowance.sol';
+
+// Consumes the MAllowance mixin
+contract Allowance is
+ IERC20Allowance,
+ MAllowance
+{
+
+////////////////
+// State
+////////////////
+
+ // `allowed` tracks any extra transfer rights as in all ERC20 tokens
+ mapping (address => mapping (address => uint256)) allowed;
+
+////////////////
+// Events
+////////////////
+
+ event Approval(
+ address indexed _owner,
+ address indexed _spender,
+ uint256 _amount
+ );
+
+////////////////
+// Constructor
+////////////////
+
+ function Allowance()
+ internal
+ {
+ }
+
+////////////////
+// Public functions
+////////////////
+
+ /// @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)
+ public
+ constant
+ returns (uint256 remaining)
+ {
+ return allowed[_owner][_spender];
+ }
+
+ /// @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)
+ public
+ returns (bool success)
+ {
+ // 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
+ require((_amount == 0) || (allowed[msg.sender][_spender] == 0));
+
+ allowed[msg.sender][_spender] = _amount;
+ Approval(msg.sender, _spender, _amount);
+ return true;
+ }
+
+ /// @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) {
+ require(approve(_spender, _amount));
+
+ IApproveAndCallFallback(_spender).receiveApproval(
+ msg.sender,
+ _amount,
+ IERC20Token(this),
+ _extraData
+ );
+
+ return true;
+ }
+
+ /// @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)
+ public
+ returns (bool success)
+ {
+ // The standard ERC 20 transferFrom functionality
+ if (allowed[_from][msg.sender] < _amount) {
+ return false;
+ }
+
+ allowed[_from][msg.sender] -= _amount;
+ return mAllowanceTransfer(_from, _to, _amount);
+ }
+
+}
diff --git a/contracts/Helpers/MAllowance.sol b/contracts/Helpers/MAllowance.sol
new file mode 100644
index 00000000..722e1d77
--- /dev/null
+++ b/contracts/Helpers/MAllowance.sol
@@ -0,0 +1,9 @@
+pragma solidity ^0.4.13;
+
+contract MAllowance {
+
+ function mAllowanceTransfer(address from, address to, uint256 amount)
+ internal
+ returns (bool);
+
+}
diff --git a/contracts/Helpers/MMint.sol b/contracts/Helpers/MMint.sol
new file mode 100644
index 00000000..3e3dc677
--- /dev/null
+++ b/contracts/Helpers/MMint.sol
@@ -0,0 +1,34 @@
+pragma solidity ^0.4.13;
+
+contract MMint {
+
+ /// @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 mTransfer(
+ address _from,
+ address _to,
+ uint _amount
+ )
+ internal
+ returns(bool);
+
+ /// @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 mGenerateTokens(address _owner, uint _amount)
+ internal
+ returns (bool);
+
+ /// @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 mDestroyTokens(address _owner, uint _amount)
+ internal
+ returns (bool);
+}
diff --git a/contracts/Helpers/SnapshotToken.sol b/contracts/Helpers/SnapshotToken.sol
new file mode 100644
index 00000000..75a5a07d
--- /dev/null
+++ b/contracts/Helpers/SnapshotToken.sol
@@ -0,0 +1,234 @@
+pragma solidity ^0.4.13;
+
+import '../Snapshot/Snapshot.sol';
+import '../Standards/ISnapshotToken.sol';
+import '../Standards/ISnapshotTokenParent.sol';
+import './MMint.sol';
+
+contract SnapshotToken is
+ ISnapshotToken,
+ ISnapshotTokenParent,
+ MMint,
+ Snapshot
+{
+
+ // `parentToken` is the Token address that was cloned to produce this token;
+ // it will be 0x0 for a token that was not cloned
+ ISnapshotTokenParent public parentToken;
+
+ // `parentSnapShotBlock` is the block number from the Parent Token that was
+ // used to determine the initial distribution of the Clone Token
+ uint256 public parentSnapshot;
+
+ // `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 => Values[]) balances;
+
+ // Tracks the history of the `totalSupply` of the token
+ Values[] totalSupplyValues;
+
+////////////////
+// Events
+////////////////
+
+ event Transfer(address indexed _from, address indexed _to, uint256 _amount);
+
+////////////////
+// Constructor
+////////////////
+
+ /// @notice Constructor to create a MiniMeToken
+ /// @param _parentToken Address of the parent token, set to 0x0 if it is a
+ /// new token
+ function SnapshotToken(
+ ISnapshotTokenParent _parentToken,
+ uint256 _parentSnapshot
+ )
+ public
+ Snapshot()
+ {
+ parentToken = _parentToken;
+ parentSnapshot = _parentSnapshot;
+ }
+
+///////////////////
+// ERC20 Basic Methods
+///////////////////
+
+ /// @dev This function makes it easy to get the total number of tokens
+ /// @return The total number of tokens
+ function totalSupply()
+ public
+ constant
+ returns (uint)
+ {
+ return getValue(totalSupplyValues, 0);
+ }
+
+ /// @param _owner The address that's balance is being requested
+ /// @return The balance of `_owner` at the current block
+ function balanceOf(address _owner)
+ public
+ constant
+ returns (uint256 balance)
+ {
+ return getValue(balances[_owner], 0);
+ }
+
+ /// @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)
+ public
+ returns (bool success)
+ {
+ return mTransfer(msg.sender, _to, _amount);
+ }
+
+////////////////
+// Query balance and totalSupply in History
+////////////////
+
+ /// @notice Total amount of tokens at a specific `_snapshot`.
+ /// @param _snapshot The block number when the totalSupply is queried
+ /// @return The total amount of tokens at `_snapshot`
+ function totalSupplyAt(uint _snapshot)
+ public
+ constant
+ returns(uint)
+ {
+ Values[] storage values = totalSupplyValues;
+
+ // If there is a value, return it
+ if (hasValueAt(values, _snapshot)) {
+ return getValueAt(values, _snapshot, 0);
+ }
+
+ // Try parent contract at or before the fork
+ if (address(parentToken) != 0) {
+ return parentToken.totalSupplyAt(parentSnapshot);
+ }
+
+ // Default to an empty balance
+ return 0;
+ }
+
+ /// @dev Queries the balance of `_owner` at a specific `_snapshot`
+ /// @param _owner The address from which the balance will be retrieved
+ /// @param _snapshot The block number when the balance is queried
+ /// @return The balance at `_snapshot`
+ function balanceOfAt(address _owner, uint _snapshot)
+ public
+ constant
+ returns (uint)
+ {
+ Values[] storage values = balances[_owner];
+
+ // If there is a value, return it
+ if (hasValueAt(values, _snapshot)) {
+ return getValueAt(values, _snapshot, 0);
+ }
+
+ // Try parent contract at or before the fork
+ if (address(parentToken) != 0) {
+ return parentToken.balanceOfAt(_owner, parentSnapshot);
+ }
+
+ // Default to an empty balance
+ return 0;
+ }
+
+////////////////
+// Generate and destroy tokens
+////////////////
+
+ /// @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 mTransfer(
+ address _from,
+ address _to,
+ uint _amount
+ )
+ internal
+ returns(bool)
+ {
+ if (_amount == 0) {
+ return true;
+ }
+
+ // If the amount being transfered is more than the balance of the
+ // account the transfer returns false
+ var previousBalanceFrom = balanceOf(_from);
+ if (previousBalanceFrom < _amount) {
+ return false;
+ }
+
+ // First update the balance array with the new value for the address
+ // sending the tokens
+ uint256 newBalanceFrom = previousBalanceFrom - _amount;
+ setValue(balances[_from], newBalanceFrom);
+
+ // Then update the balance array with the new value for the address
+ // receiving the tokens
+ uint256 previousBalanceTo = balanceOf(_to);
+ uint256 newBalanceTo = previousBalanceTo + _amount;
+ assert(newBalanceTo >= previousBalanceTo); // Check for overflow
+ setValue(balances[_to], newBalanceTo);
+
+ // An event to make the transfer easy to find on the blockchain
+ Transfer(_from, _to, _amount);
+ return true;
+ }
+
+ /// @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 mGenerateTokens(address _owner, uint _amount)
+ internal
+ returns (bool)
+ {
+ uint curTotalSupply = totalSupply();
+ uint256 newTotalSupply = curTotalSupply + _amount;
+ require(newTotalSupply >= curTotalSupply); // Check for overflow
+
+ uint previousBalanceTo = balanceOf(_owner);
+ uint256 newBalanceTo = previousBalanceTo + _amount;
+ assert(newBalanceTo >= previousBalanceTo); // Check for overflow
+
+ setValue(totalSupplyValues, newTotalSupply);
+ setValue(balances[_owner], newBalanceTo);
+
+ 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 mDestroyTokens(address _owner, uint _amount)
+ internal
+ returns (bool)
+ {
+ uint curTotalSupply = totalSupply();
+ require(curTotalSupply >= _amount);
+
+ uint previousBalanceFrom = balanceOf(_owner);
+ require(previousBalanceFrom >= _amount);
+
+ uint newTotalSupply = curTotalSupply - _amount;
+ uint newBalanceFrom = previousBalanceFrom - _amount;
+ setValue(totalSupplyValues, newTotalSupply);
+ setValue(balances[_owner], newBalanceFrom);
+
+ Transfer(_owner, 0, _amount);
+ return true;
+ }
+}
diff --git a/contracts/Helpers/TokenInfo.sol b/contracts/Helpers/TokenInfo.sol
new file mode 100644
index 00000000..ccecf750
--- /dev/null
+++ b/contracts/Helpers/TokenInfo.sol
@@ -0,0 +1,26 @@
+pragma solidity ^0.4.13;
+
+
+contract TokenInfo {
+
+ 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; //An arbitrary versioning scheme
+
+ /// @notice Constructor to create a MiniMeToken
+ /// @param _tokenName Name of the new token
+ /// @param _decimalUnits Number of decimals of the new token
+ /// @param _tokenSymbol Token Symbol for the new token
+ function TokenInfo(
+ string _tokenName,
+ uint8 _decimalUnits,
+ string _tokenSymbol,
+ string _version
+ ) {
+ name = _tokenName; // Set the name
+ decimals = _decimalUnits; // Set the decimals
+ symbol = _tokenSymbol; // Set the symbol
+ version = _version;
+ }
+}
diff --git a/contracts/ITokenController.sol b/contracts/ITokenController.sol
new file mode 100644
index 00000000..9fa40784
--- /dev/null
+++ b/contracts/ITokenController.sol
@@ -0,0 +1,30 @@
+pragma solidity ^0.4.13;
+
+/// @dev The token controller contract must implement these functions
+contract ITokenController {
+
+ // Payable callback function to receive eth
+ function () payable;
+
+ /// @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);
+}
diff --git a/contracts/IsContract.sol b/contracts/IsContract.sol
new file mode 100644
index 00000000..f8031e9b
--- /dev/null
+++ b/contracts/IsContract.sol
@@ -0,0 +1,24 @@
+pragma solidity ^0.4.13;
+
+contract IsContract {
+
+ function IsContract() internal {}
+
+ /// @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)
+ internal
+ constant
+ returns (bool)
+ {
+ uint size;
+ if (_addr == 0) {
+ return false; // TODO: Is this necessary?
+ }
+ assembly {
+ size := extcodesize(_addr)
+ }
+ return size > 0;
+ }
+}
diff --git a/contracts/MiniMeToken.sol b/contracts/MiniMeToken.sol
deleted file mode 100644
index 404d071b..00000000
--- a/contracts/MiniMeToken.sol
+++ /dev/null
@@ -1,602 +0,0 @@
-pragma solidity ^0.4.6;
-
-/*
- 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 { require(msg.sender == controller); _; }
-
- 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 = block.number;
- }
-
-
-///////////////////
-// 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) {
- require(transfersEnabled);
- 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) {
- require(transfersEnabled);
-
- // 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;
- }
-
- require(parentSnapShotBlock < block.number);
-
- // Do not allow transfer to 0x0 or the token contract itself
- require((_to != 0) && (_to != address(this)));
-
- // If the amount being transfered is more than the balance of the
- // account the transfer returns false
- var previousBalanceFrom = balanceOfAt(_from, block.number);
- if (previousBalanceFrom < _amount) {
- return false;
- }
-
- // Alerts the token controller of the transfer
- if (isContract(controller)) {
- require(TokenController(controller).onTransfer(_from, _to, _amount));
- }
-
- // 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, block.number);
- require(previousBalanceTo + _amount >= previousBalanceTo); // 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, block.number);
- }
-
- /// @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) {
- require(transfersEnabled);
-
- // 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
- require((_amount == 0) || (allowed[msg.sender][_spender] == 0));
-
- // Alerts the token controller of the approve function call
- if (isContract(controller)) {
- require(TokenController(controller).onApprove(msg.sender, _spender, _amount));
- }
-
- 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) {
- require(approve(_spender, _amount));
-
- 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(block.number);
- }
-
-
-////////////////
-// 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 = block.number;
- 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 = totalSupply();
- require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow
- uint previousBalanceTo = balanceOf(_owner);
- require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
- updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
- 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 = totalSupply();
- require(curTotalSupply >= _amount);
- uint previousBalanceFrom = balanceOf(_owner);
- require(previousBalanceFrom >= _amount);
- updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
- 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 < block.number)) {
- Checkpoint storage newCheckPoint = checkpoints[ checkpoints.length++ ];
- newCheckPoint.fromBlock = uint128(block.number);
- newCheckPoint.value = uint128(_value);
- } else {
- Checkpoint storage 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 {
- require(isContract(controller));
- require(TokenController(controller).proxyPayment.value(msg.value)(msg.sender));
- }
-
-//////////
-// 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;
- }
-
- MiniMeToken token = MiniMeToken(_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;
- }
-}
diff --git a/contracts/MiniMeToken.sol.js b/contracts/MiniMeToken.sol.js
deleted file mode 100644
index c95a7c46..00000000
--- a/contracts/MiniMeToken.sol.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This is an autogenerated file. DO NOT EDIT MANUALLY */
-
-exports.ApproveAndCallFallBackAbi = [{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_token","type":"address"},{"name":"_data","type":"bytes"}],"name":"receiveApproval","outputs":[],"payable":false,"type":"function"}];
-exports.ApproveAndCallFallBackByteCode = "0x";
-exports.ControlledAbi = [{"constant":false,"inputs":[{"name":"_newController","type":"address"}],"name":"changeController","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}];
-exports.ControlledByteCode = "0x6060604052341561000f57600080fd5b5b60008054600160a060020a03191633600160a060020a03161790555b5b61015c8061003c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633cebb8238114610048578063f77c479114610076575b600080fd5b341561005357600080fd5b61007473ffffffffffffffffffffffffffffffffffffffff600435166100b2565b005b341561008157600080fd5b610089610114565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000543373ffffffffffffffffffffffffffffffffffffffff9081169116146100da57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff191673ffffffffffffffffffffffffffffffffffffffff83161790555b5b50565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a723058203f3045b685137a5d9d154e3daf1770e03174caa4eafc08998d51f50d5015a1e00029";
-exports.MiniMeTokenAbi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"creationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newController","type":"address"}],"name":"changeController","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_blockNumber","type":"uint256"}],"name":"balanceOfAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_cloneTokenName","type":"string"},{"name":"_cloneDecimalUnits","type":"uint8"},{"name":"_cloneTokenSymbol","type":"string"},{"name":"_snapshotBlock","type":"uint256"},{"name":"_transfersEnabled","type":"bool"}],"name":"createCloneToken","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"parentToken","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_amount","type":"uint256"}],"name":"generateTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_blockNumber","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"transfersEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"parentSnapShotBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_amount","type":"uint256"}],"name":"destroyTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"claimTokens","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"tokenFactory","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_transfersEnabled","type":"bool"}],"name":"enableTransfers","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"_tokenFactory","type":"address"},{"name":"_parentToken","type":"address"},{"name":"_parentSnapShotBlock","type":"uint256"},{"name":"_tokenName","type":"string"},{"name":"_decimalUnits","type":"uint8"},{"name":"_tokenSymbol","type":"string"},{"name":"_transfersEnabled","type":"bool"}],"payable":false,"type":"constructor"},{"payable":true,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_token","type":"address"},{"indexed":true,"name":"_controller","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"ClaimedTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_cloneToken","type":"address"},{"indexed":false,"name":"_snapshotBlock","type":"uint256"}],"name":"NewCloneToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Approval","type":"event"}];
-exports.MiniMeTokenByteCode = "0x606060405260408051908101604052600781527f4d4d545f302e3100000000000000000000000000000000000000000000000000602082015260049080516200004d9291602001906200015c565b5034156200005a57600080fd5b60405162001d6038038062001d6083398101604052808051919060200180519190602001805191906020018051820191906020018051919060200180518201919060200180519150505b5b60008054600160a060020a03191633600160a060020a03161790555b600b805461010060a860020a031916610100600160a060020a038a16021790556001848051620000f69291602001906200015c565b506002805460ff191660ff851617905560038280516200011b9291602001906200015c565b5060058054600160a060020a031916600160a060020a0388161790556006859055600b805460ff1916821515179055436007555b5050505050505062000206565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200019f57805160ff1916838001178555620001cf565b82800160010185558215620001cf579182015b82811115620001cf578251825591602001919060010190620001b2565b5b50620001de929150620001e2565b5090565b6200020391905b80821115620001de5760008155600101620001e9565b5090565b90565b611b4a80620002166000396000f3006060604052361561012d5763ffffffff60e060020a60003504166306fdde0381146101d9578063095ea7b314610264578063176345141461029a57806318160ddd146102bf57806323b872dd146102e4578063313ce567146103205780633cebb823146103495780634ee2cd7e1461036a57806354fd4d501461039e5780636638c0871461042957806370a08231146104ed57806380a540011461051e578063827f32c01461054d57806395d89b4114610583578063981b24d01461060e578063a9059cbb14610636578063bef97c871461066c578063c5bcc4f114610693578063cae9ca51146106b8578063d3ce77fe14610731578063dd62ed3e14610767578063df8de3e71461079e578063e77772fe146107bf578063f41e60c5146107ee578063f77c479114610808575b6101d75b60005461014690600160a060020a0316610837565b151561015157600080fd5b60008054600160a060020a03169063f48c305490349033906040516020015260405160e060020a63ffffffff8516028152600160a060020a0390911660048201526024016020604051808303818588803b15156101ad57600080fd5b6125ee5a03f115156101be57600080fd5b505050506040518051905015156101d457600080fd5b5b565b005b34156101e457600080fd5b6101ec610864565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156102295780820151818401525b602001610210565b50505050905090810190601f1680156102565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561026f57600080fd5b610286600160a060020a0360043516602435610902565b604051901515815260200160405180910390f35b34156102a557600080fd5b6102ad610a6c565b60405190815260200160405180910390f35b34156102ca57600080fd5b6102ad610a72565b60405190815260200160405180910390f35b34156102ef57600080fd5b610286600160a060020a0360043581169060243516604435610a83565b604051901515815260200160405180910390f35b341561032b57600080fd5b610333610b25565b60405160ff909116815260200160405180910390f35b341561035457600080fd5b6101d7600160a060020a0360043516610b2e565b005b341561037557600080fd5b6102ad600160a060020a0360043516602435610b76565b60405190815260200160405180910390f35b34156103a957600080fd5b6101ec610cbc565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156102295780820151818401525b602001610210565b50505050905090810190601f1680156102565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561043457600080fd5b6104d160046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803560ff1690602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528181529291906020840183838082843750949650508435946020013515159350610d5a92505050565b604051600160a060020a03909116815260200160405180910390f35b34156104f857600080fd5b6102ad600160a060020a0360043516610f8a565b60405190815260200160405180910390f35b341561052957600080fd5b6104d1610f9e565b604051600160a060020a03909116815260200160405180910390f35b341561055857600080fd5b610286600160a060020a0360043516602435610fad565b604051901515815260200160405180910390f35b341561058e57600080fd5b6101ec611080565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156102295780820151818401525b602001610210565b50505050905090810190601f1680156102565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561061957600080fd5b6102ad60043561111e565b60405190815260200160405180910390f35b341561064157600080fd5b610286600160a060020a0360043516602435611216565b604051901515815260200160405180910390f35b341561067757600080fd5b61028661123e565b604051901515815260200160405180910390f35b341561069e57600080fd5b6102ad611247565b60405190815260200160405180910390f35b34156106c357600080fd5b61028660048035600160a060020a03169060248035919060649060443590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061124d95505050505050565b604051901515815260200160405180910390f35b341561073c57600080fd5b610286600160a060020a036004351660243561136b565b604051901515815260200160405180910390f35b341561077257600080fd5b6102ad600160a060020a0360043581169060243516611438565b60405190815260200160405180910390f35b34156107a957600080fd5b6101d7600160a060020a0360043516611465565b005b34156107ca57600080fd5b6104d1611612565b604051600160a060020a03909116815260200160405180910390f35b34156107f957600080fd5b6101d76004351515611626565b005b341561081357600080fd5b6104d1611654565b604051600160a060020a03909116815260200160405180910390f35b600080600160a060020a0383161515610853576000915061085e565b823b90506000811191505b50919050565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108fa5780601f106108cf576101008083540402835291602001916108fa565b820191906000526020600020905b8154815290600101906020018083116108dd57829003601f168201915b505050505081565b600b5460009060ff16151561091657600080fd5b8115806109465750600160a060020a03338116600090815260096020908152604080832093871683529290522054155b151561095157600080fd5b60005461096690600160a060020a0316610837565b15610a015760008054600160a060020a03169063da682aeb903390869086906040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b15156109db57600080fd5b6102c65a03f115156109ec57600080fd5b505050604051805190501515610a0157600080fd5b5b600160a060020a03338116600081815260096020908152604080832094881680845294909152908190208590557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b60075481565b6000610a7d4361111e565b90505b90565b6000805433600160a060020a03908116911614610b1057600b5460ff161515610aab57600080fd5b600160a060020a038085166000908152600960209081526040808320339094168352929052205482901015610ae257506000610b1e565b600160a060020a03808516600090815260096020908152604080832033909416835292905220805483900390555b610b1b848484611663565b90505b9392505050565b60025460ff1681565b60005433600160a060020a03908116911614610b4957600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600160a060020a0382166000908152600860205260408120541580610bd65750600160a060020a038316600090815260086020526040812080548492908110610bbb57fe5b906000526020600020900160005b50546001608060020a0316115b15610c8c57600554600160a060020a031615610c7f57600554600654600160a060020a0390911690634ee2cd7e908590610c11908690611842565b60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610c5d57600080fd5b6102c65a03f11515610c6e57600080fd5b505050604051805190509050610a66565b506000610a66565b610a66565b600160a060020a0383166000908152600860205260409020610cae908361185c565b9050610a66565b5b92915050565b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108fa5780601f106108cf576101008083540402835291602001916108fa565b820191906000526020600020905b8154815290600101906020018083116108dd57829003601f168201915b505050505081565b600080831515610d68574393505b600b546101009004600160a060020a0316635b7b72c130868a8a8a8960006040516020015260405160e060020a63ffffffff8916028152600160a060020a038716600482019081526024820187905260ff8516606483015282151560a483015260c0604483019081529091608481019060c40187818151815260200191508051906020019080838360005b83811015610e0c5780820151818401525b602001610df3565b50505050905090810190601f168015610e395780820380516001836020036101000a031916815260200191505b50838103825285818151815260200191508051906020019080838360005b83811015610e705780820151818401525b602001610e57565b50505050905090810190601f168015610e9d5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1515610ec157600080fd5b6102c65a03f11515610ed257600080fd5b5050506040518051915050600160a060020a038116633cebb8233360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401600060405180830381600087803b1515610f2b57600080fd5b6102c65a03f11515610f3c57600080fd5b50505080600160a060020a03167f086c875b377f900b07ce03575813022f05dd10ed7640b5282cf6d3c3fc352ade8560405190815260200160405180910390a28091505b5095945050505050565b6000610f968243610b76565b90505b919050565b600554600160a060020a031681565b600080548190819033600160a060020a03908116911614610fcd57600080fd5b610fd5610a72565b915083820182901015610fe757600080fd5b610ff085610f8a565b90508381018190101561100257600080fd5b61100f600a8584016119d0565b600160a060020a0385166000908152600860205260409020611033908286016119d0565b84600160a060020a031660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8660405190815260200160405180910390a3600192505b5b505092915050565b60038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108fa5780601f106108cf576101008083540402835291602001916108fa565b820191906000526020600020905b8154815290600101906020018083116108dd57829003601f168201915b505050505081565b600a546000901580611157575081600a600081548110151561113c57fe5b906000526020600020900160005b50546001608060020a0316115b156111fe57600554600160a060020a0316156111f157600554600654600160a060020a039091169063981b24d090611190908590611842565b60006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156111cf57600080fd5b6102c65a03f115156111e057600080fd5b505050604051805190509050610f99565b506000610f99565b610f99565b611209600a8361185c565b9050610f99565b5b919050565b600b5460009060ff16151561122a57600080fd5b611235338484611663565b90505b92915050565b600b5460ff1681565b60065481565b60006112598484610902565b151561126457600080fd5b83600160a060020a0316638f4ffcb1338530866040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156112fd5780820151818401525b6020016112e4565b50505050905090810190601f16801561132a5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b151561134b57600080fd5b6102c65a03f1151561135c57600080fd5b505050600190505b9392505050565b600080548190819033600160a060020a0390811691161461138b57600080fd5b611393610a72565b9150838210156113a257600080fd5b6113ab85610f8a565b9050838110156113ba57600080fd5b6113c7600a8584036119d0565b600160a060020a03851660009081526008602052604090206113eb908583036119d0565b600085600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8660405190815260200160405180910390a3600192505b5b505092915050565b600160a060020a038083166000908152600960209081526040808320938516835292905220545b92915050565b60008054819033600160a060020a0390811691161461148357600080fd5b600160a060020a03831615156114d157600054600160a060020a039081169030163180156108fc0290604051600060405180830381858888f1935050505015156114cc57600080fd5b61160c565b82915081600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561152b57600080fd5b6102c65a03f1151561153c57600080fd5b505050604051805160008054919350600160a060020a03808616935063a9059cbb92169084906040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156115ac57600080fd5b6102c65a03f115156115bd57600080fd5b50505060405180515050600054600160a060020a039081169084167ff931edb47c50b4b4104c187b5814a9aef5f709e17e2ecf9617e860cacade929c8360405190815260200160405180910390a35b5b505050565b600b546101009004600160a060020a031681565b60005433600160a060020a0390811691161461164157600080fd5b600b805460ff19168215151790555b5b50565b600054600160a060020a031681565b600080808315156116775760019250611839565b60065443901061168657600080fd5b600160a060020a038516158015906116b0575030600160a060020a031685600160a060020a031614155b15156116bb57600080fd5b6116c58643610b76565b9150838210156116d85760009250611839565b6000546116ed90600160a060020a0316610837565b156117885760008054600160a060020a031690634a393149908890889088906040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b151561176257600080fd5b6102c65a03f1151561177357600080fd5b50505060405180519050151561178857600080fd5b5b600160a060020a03861660009081526008602052604090206117ad908584036119d0565b6117b78543610b76565b9050838101819010156117c957600080fd5b600160a060020a03851660009081526008602052604090206117ed908286016119d0565b84600160a060020a031686600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8660405190815260200160405180910390a3600192505b50509392505050565b60008183106118515781611235565b825b90505b92915050565b60008060008085805490506000141561187857600093506119c7565b85548690600019810190811061188a57fe5b906000526020600020900160005b50546001608060020a031685106118ef578554869060001981019081106118bb57fe5b906000526020600020900160005b505470010000000000000000000000000000000090046001608060020a031693506119c7565b8560008154811015156118fe57fe5b906000526020600020900160005b50546001608060020a031685101561192757600093506119c7565b8554600093506000190191505b828211156119895760026001838501015b04905084868281548110151561195757fe5b906000526020600020900160005b50546001608060020a03161161197d57809250611984565b6001810391505b611934565b858381548110151561199757fe5b906000526020600020900160005b505470010000000000000000000000000000000090046001608060020a031693505b50505092915050565b815460009081901580611a0d575083544390859060001981019081106119f257fe5b906000526020600020900160005b50546001608060020a0316105b15611a835783548490611a238260018301611ad3565b81548110611a2d57fe5b906000526020600020900160005b5080546001608060020a03858116700100000000000000000000000000000000024382166fffffffffffffffffffffffffffffffff1990931692909217161781559150611acc565b835484906000198101908110611a9557fe5b906000526020600020900160005b5080546001608060020a0380861670010000000000000000000000000000000002911617815590505b5b50505050565b81548183558181151161160c5760008381526020902061160c918101908301611afd565b5b505050565b610a8091905b80821115611b175760008155600101611b03565b5090565b905600a165627a7a72305820a65b405eae3c826d2caab3069766b9c4b6f8bf64ce0b2eca671930e1a3736c480029";
-exports.MiniMeTokenFactoryAbi = [{"constant":false,"inputs":[{"name":"_parentToken","type":"address"},{"name":"_snapshotBlock","type":"uint256"},{"name":"_tokenName","type":"string"},{"name":"_decimalUnits","type":"uint8"},{"name":"_tokenSymbol","type":"string"},{"name":"_transfersEnabled","type":"bool"}],"name":"createCloneToken","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}];
-exports.MiniMeTokenFactoryByteCode = "0x6060604052341561000f57600080fd5b5b6120ac8061001f6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416635b7b72c1811461003d575b600080fd5b341561004857600080fd5b6101016004803573ffffffffffffffffffffffffffffffffffffffff169060248035919060649060443590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803560ff1690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052818152929190602084018383808284375094965050505091351515915061012a9050565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000803088888888888861013c610310565b73ffffffffffffffffffffffffffffffffffffffff8089168252871660208201526040810186905260ff8416608082015281151560c082015260e0606082018181529060a0830190830187818151815260200191508051906020019080838360005b838110156101b75780820151818401525b60200161019e565b50505050905090810190601f1680156101e45780820380516001836020036101000a031916815260200191505b50838103825285818151815260200191508051906020019080838360005b8381101561021b5780820151818401525b602001610202565b50505050905090810190601f1680156102485780820380516001836020036101000a031916815260200191505b509950505050505050505050604051809103906000f080151561026a57600080fd5b90508073ffffffffffffffffffffffffffffffffffffffff16633cebb823336040517c010000000000000000000000000000000000000000000000000000000063ffffffff841602815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15156102ed57600080fd5b6102c65a03f115156102fe57600080fd5b5050508091505b509695505050505050565b604051611d6080610321833901905600606060405260408051908101604052600781527f4d4d545f302e3100000000000000000000000000000000000000000000000000602082015260049080516200004d9291602001906200015c565b5034156200005a57600080fd5b60405162001d6038038062001d6083398101604052808051919060200180519190602001805191906020018051820191906020018051919060200180518201919060200180519150505b5b60008054600160a060020a03191633600160a060020a03161790555b600b805461010060a860020a031916610100600160a060020a038a16021790556001848051620000f69291602001906200015c565b506002805460ff191660ff851617905560038280516200011b9291602001906200015c565b5060058054600160a060020a031916600160a060020a0388161790556006859055600b805460ff1916821515179055436007555b5050505050505062000206565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200019f57805160ff1916838001178555620001cf565b82800160010185558215620001cf579182015b82811115620001cf578251825591602001919060010190620001b2565b5b50620001de929150620001e2565b5090565b6200020391905b80821115620001de5760008155600101620001e9565b5090565b90565b611b4a80620002166000396000f3006060604052361561012d5763ffffffff60e060020a60003504166306fdde0381146101d9578063095ea7b314610264578063176345141461029a57806318160ddd146102bf57806323b872dd146102e4578063313ce567146103205780633cebb823146103495780634ee2cd7e1461036a57806354fd4d501461039e5780636638c0871461042957806370a08231146104ed57806380a540011461051e578063827f32c01461054d57806395d89b4114610583578063981b24d01461060e578063a9059cbb14610636578063bef97c871461066c578063c5bcc4f114610693578063cae9ca51146106b8578063d3ce77fe14610731578063dd62ed3e14610767578063df8de3e71461079e578063e77772fe146107bf578063f41e60c5146107ee578063f77c479114610808575b6101d75b60005461014690600160a060020a0316610837565b151561015157600080fd5b60008054600160a060020a03169063f48c305490349033906040516020015260405160e060020a63ffffffff8516028152600160a060020a0390911660048201526024016020604051808303818588803b15156101ad57600080fd5b6125ee5a03f115156101be57600080fd5b505050506040518051905015156101d457600080fd5b5b565b005b34156101e457600080fd5b6101ec610864565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156102295780820151818401525b602001610210565b50505050905090810190601f1680156102565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561026f57600080fd5b610286600160a060020a0360043516602435610902565b604051901515815260200160405180910390f35b34156102a557600080fd5b6102ad610a6c565b60405190815260200160405180910390f35b34156102ca57600080fd5b6102ad610a72565b60405190815260200160405180910390f35b34156102ef57600080fd5b610286600160a060020a0360043581169060243516604435610a83565b604051901515815260200160405180910390f35b341561032b57600080fd5b610333610b25565b60405160ff909116815260200160405180910390f35b341561035457600080fd5b6101d7600160a060020a0360043516610b2e565b005b341561037557600080fd5b6102ad600160a060020a0360043516602435610b76565b60405190815260200160405180910390f35b34156103a957600080fd5b6101ec610cbc565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156102295780820151818401525b602001610210565b50505050905090810190601f1680156102565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561043457600080fd5b6104d160046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803560ff1690602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528181529291906020840183838082843750949650508435946020013515159350610d5a92505050565b604051600160a060020a03909116815260200160405180910390f35b34156104f857600080fd5b6102ad600160a060020a0360043516610f8a565b60405190815260200160405180910390f35b341561052957600080fd5b6104d1610f9e565b604051600160a060020a03909116815260200160405180910390f35b341561055857600080fd5b610286600160a060020a0360043516602435610fad565b604051901515815260200160405180910390f35b341561058e57600080fd5b6101ec611080565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156102295780820151818401525b602001610210565b50505050905090810190601f1680156102565780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561061957600080fd5b6102ad60043561111e565b60405190815260200160405180910390f35b341561064157600080fd5b610286600160a060020a0360043516602435611216565b604051901515815260200160405180910390f35b341561067757600080fd5b61028661123e565b604051901515815260200160405180910390f35b341561069e57600080fd5b6102ad611247565b60405190815260200160405180910390f35b34156106c357600080fd5b61028660048035600160a060020a03169060248035919060649060443590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061124d95505050505050565b604051901515815260200160405180910390f35b341561073c57600080fd5b610286600160a060020a036004351660243561136b565b604051901515815260200160405180910390f35b341561077257600080fd5b6102ad600160a060020a0360043581169060243516611438565b60405190815260200160405180910390f35b34156107a957600080fd5b6101d7600160a060020a0360043516611465565b005b34156107ca57600080fd5b6104d1611612565b604051600160a060020a03909116815260200160405180910390f35b34156107f957600080fd5b6101d76004351515611626565b005b341561081357600080fd5b6104d1611654565b604051600160a060020a03909116815260200160405180910390f35b600080600160a060020a0383161515610853576000915061085e565b823b90506000811191505b50919050565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108fa5780601f106108cf576101008083540402835291602001916108fa565b820191906000526020600020905b8154815290600101906020018083116108dd57829003601f168201915b505050505081565b600b5460009060ff16151561091657600080fd5b8115806109465750600160a060020a03338116600090815260096020908152604080832093871683529290522054155b151561095157600080fd5b60005461096690600160a060020a0316610837565b15610a015760008054600160a060020a03169063da682aeb903390869086906040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b15156109db57600080fd5b6102c65a03f115156109ec57600080fd5b505050604051805190501515610a0157600080fd5b5b600160a060020a03338116600081815260096020908152604080832094881680845294909152908190208590557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b60075481565b6000610a7d4361111e565b90505b90565b6000805433600160a060020a03908116911614610b1057600b5460ff161515610aab57600080fd5b600160a060020a038085166000908152600960209081526040808320339094168352929052205482901015610ae257506000610b1e565b600160a060020a03808516600090815260096020908152604080832033909416835292905220805483900390555b610b1b848484611663565b90505b9392505050565b60025460ff1681565b60005433600160a060020a03908116911614610b4957600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600160a060020a0382166000908152600860205260408120541580610bd65750600160a060020a038316600090815260086020526040812080548492908110610bbb57fe5b906000526020600020900160005b50546001608060020a0316115b15610c8c57600554600160a060020a031615610c7f57600554600654600160a060020a0390911690634ee2cd7e908590610c11908690611842565b60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610c5d57600080fd5b6102c65a03f11515610c6e57600080fd5b505050604051805190509050610a66565b506000610a66565b610a66565b600160a060020a0383166000908152600860205260409020610cae908361185c565b9050610a66565b5b92915050565b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108fa5780601f106108cf576101008083540402835291602001916108fa565b820191906000526020600020905b8154815290600101906020018083116108dd57829003601f168201915b505050505081565b600080831515610d68574393505b600b546101009004600160a060020a0316635b7b72c130868a8a8a8960006040516020015260405160e060020a63ffffffff8916028152600160a060020a038716600482019081526024820187905260ff8516606483015282151560a483015260c0604483019081529091608481019060c40187818151815260200191508051906020019080838360005b83811015610e0c5780820151818401525b602001610df3565b50505050905090810190601f168015610e395780820380516001836020036101000a031916815260200191505b50838103825285818151815260200191508051906020019080838360005b83811015610e705780820151818401525b602001610e57565b50505050905090810190601f168015610e9d5780820380516001836020036101000a031916815260200191505b5098505050505050505050602060405180830381600087803b1515610ec157600080fd5b6102c65a03f11515610ed257600080fd5b5050506040518051915050600160a060020a038116633cebb8233360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401600060405180830381600087803b1515610f2b57600080fd5b6102c65a03f11515610f3c57600080fd5b50505080600160a060020a03167f086c875b377f900b07ce03575813022f05dd10ed7640b5282cf6d3c3fc352ade8560405190815260200160405180910390a28091505b5095945050505050565b6000610f968243610b76565b90505b919050565b600554600160a060020a031681565b600080548190819033600160a060020a03908116911614610fcd57600080fd5b610fd5610a72565b915083820182901015610fe757600080fd5b610ff085610f8a565b90508381018190101561100257600080fd5b61100f600a8584016119d0565b600160a060020a0385166000908152600860205260409020611033908286016119d0565b84600160a060020a031660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8660405190815260200160405180910390a3600192505b5b505092915050565b60038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108fa5780601f106108cf576101008083540402835291602001916108fa565b820191906000526020600020905b8154815290600101906020018083116108dd57829003601f168201915b505050505081565b600a546000901580611157575081600a600081548110151561113c57fe5b906000526020600020900160005b50546001608060020a0316115b156111fe57600554600160a060020a0316156111f157600554600654600160a060020a039091169063981b24d090611190908590611842565b60006040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156111cf57600080fd5b6102c65a03f115156111e057600080fd5b505050604051805190509050610f99565b506000610f99565b610f99565b611209600a8361185c565b9050610f99565b5b919050565b600b5460009060ff16151561122a57600080fd5b611235338484611663565b90505b92915050565b600b5460ff1681565b60065481565b60006112598484610902565b151561126457600080fd5b83600160a060020a0316638f4ffcb1338530866040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156112fd5780820151818401525b6020016112e4565b50505050905090810190601f16801561132a5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b151561134b57600080fd5b6102c65a03f1151561135c57600080fd5b505050600190505b9392505050565b600080548190819033600160a060020a0390811691161461138b57600080fd5b611393610a72565b9150838210156113a257600080fd5b6113ab85610f8a565b9050838110156113ba57600080fd5b6113c7600a8584036119d0565b600160a060020a03851660009081526008602052604090206113eb908583036119d0565b600085600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8660405190815260200160405180910390a3600192505b5b505092915050565b600160a060020a038083166000908152600960209081526040808320938516835292905220545b92915050565b60008054819033600160a060020a0390811691161461148357600080fd5b600160a060020a03831615156114d157600054600160a060020a039081169030163180156108fc0290604051600060405180830381858888f1935050505015156114cc57600080fd5b61160c565b82915081600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561152b57600080fd5b6102c65a03f1151561153c57600080fd5b505050604051805160008054919350600160a060020a03808616935063a9059cbb92169084906040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156115ac57600080fd5b6102c65a03f115156115bd57600080fd5b50505060405180515050600054600160a060020a039081169084167ff931edb47c50b4b4104c187b5814a9aef5f709e17e2ecf9617e860cacade929c8360405190815260200160405180910390a35b5b505050565b600b546101009004600160a060020a031681565b60005433600160a060020a0390811691161461164157600080fd5b600b805460ff19168215151790555b5b50565b600054600160a060020a031681565b600080808315156116775760019250611839565b60065443901061168657600080fd5b600160a060020a038516158015906116b0575030600160a060020a031685600160a060020a031614155b15156116bb57600080fd5b6116c58643610b76565b9150838210156116d85760009250611839565b6000546116ed90600160a060020a0316610837565b156117885760008054600160a060020a031690634a393149908890889088906040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b151561176257600080fd5b6102c65a03f1151561177357600080fd5b50505060405180519050151561178857600080fd5b5b600160a060020a03861660009081526008602052604090206117ad908584036119d0565b6117b78543610b76565b9050838101819010156117c957600080fd5b600160a060020a03851660009081526008602052604090206117ed908286016119d0565b84600160a060020a031686600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8660405190815260200160405180910390a3600192505b50509392505050565b60008183106118515781611235565b825b90505b92915050565b60008060008085805490506000141561187857600093506119c7565b85548690600019810190811061188a57fe5b906000526020600020900160005b50546001608060020a031685106118ef578554869060001981019081106118bb57fe5b906000526020600020900160005b505470010000000000000000000000000000000090046001608060020a031693506119c7565b8560008154811015156118fe57fe5b906000526020600020900160005b50546001608060020a031685101561192757600093506119c7565b8554600093506000190191505b828211156119895760026001838501015b04905084868281548110151561195757fe5b906000526020600020900160005b50546001608060020a03161161197d57809250611984565b6001810391505b611934565b858381548110151561199757fe5b906000526020600020900160005b505470010000000000000000000000000000000090046001608060020a031693505b50505092915050565b815460009081901580611a0d575083544390859060001981019081106119f257fe5b906000526020600020900160005b50546001608060020a0316105b15611a835783548490611a238260018301611ad3565b81548110611a2d57fe5b906000526020600020900160005b5080546001608060020a03858116700100000000000000000000000000000000024382166fffffffffffffffffffffffffffffffff1990931692909217161781559150611acc565b835484906000198101908110611a9557fe5b906000526020600020900160005b5080546001608060020a0380861670010000000000000000000000000000000002911617815590505b5b50505050565b81548183558181151161160c5760008381526020902061160c918101908301611afd565b5b505050565b610a8091905b80821115611b175760008155600101611b03565b5090565b905600a165627a7a72305820a65b405eae3c826d2caab3069766b9c4b6f8bf64ce0b2eca671930e1a3736c480029a165627a7a72305820276428d6222c43dee21a55759845b8ade771ea1b6d90ef46fcfff751688a5a690029";
-exports.TokenControllerAbi = [{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"onTransfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"onApprove","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"proxyPayment","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"}];
-exports.TokenControllerByteCode = "0x";
diff --git a/contracts/Snapshot/Daily.sol b/contracts/Snapshot/Daily.sol
new file mode 100644
index 00000000..0716275b
--- /dev/null
+++ b/contracts/Snapshot/Daily.sol
@@ -0,0 +1,35 @@
+pragma solidity ^0.4.13;
+
+import './MPolicy.sol';
+
+contract Daily is MPolicy {
+
+ function snapshotAt(uint256 timestamp)
+ public
+ constant
+ returns (uint256)
+ {
+ // Round down to the start of the day (00:00 UTC)
+ timestamp -= timestamp % 1 days;
+
+ return timestamp;
+ }
+
+ function mNextSnapshotId()
+ internal
+ returns (uint256)
+ {
+ // Take the current time in UTC
+ uint256 timestamp = block.timestamp;
+
+ // Round down to the start of the day (00:00 UTC)
+ timestamp -= timestamp % 1 days;
+
+ return timestamp;
+ }
+
+ function mFlagSnapshotModified()
+ internal
+ {
+ }
+}
diff --git a/contracts/Snapshot/DailyAndSnapshotable.sol b/contracts/Snapshot/DailyAndSnapshotable.sol
new file mode 100644
index 00000000..9119c1b6
--- /dev/null
+++ b/contracts/Snapshot/DailyAndSnapshotable.sol
@@ -0,0 +1,95 @@
+pragma solidity ^0.4.13;
+
+import '../Standards/ISnapshotable.sol';
+import './MPolicy.sol';
+
+contract DailyAndSnapshotable is
+ MPolicy,
+ ISnapshotable
+{
+
+ // Floor[2**128 / 1 days]
+ uint256 MAX_TIMESTAMP = 3938453320844195178974243141571391;
+
+ uint256 nextSnapshotId;
+ bool nextSnapshotModified;
+
+ function DailyAndSnapshotable() {
+ uint256 dayBase = 2**128 * (block.timestamp / 1 days);
+ nextSnapshotId = dayBase + 1;
+ nextSnapshotModified = false;
+ }
+
+ function snapshotAt(uint256 timestamp)
+ public
+ constant
+ returns (uint256)
+ {
+ require(timestamp < MAX_TIMESTAMP);
+
+ uint256 dayBase = 2**128 * (timestamp / 1 days);
+ return dayBase;
+ }
+
+ function createSnapshot()
+ public
+ returns (uint256)
+ {
+ uint256 dayBase = 2**128 * (block.timestamp / 1 days);
+
+ // New day has started, create snapshot for midnight
+ if (dayBase > nextSnapshotId) {
+ nextSnapshotId = dayBase + 1;
+ nextSnapshotModified = false;
+
+ SnapshotCreated(dayBase);
+ return dayBase;
+ }
+
+ // Same day, no modifications
+ if (!nextSnapshotModified) {
+ uint256 previousSnapshot = nextSnapshotId - 1;
+
+ // Log the event anyway, some logic may depend
+ // depend on it.
+ SnapshotCreated(previousSnapshot);
+ return previousSnapshot;
+ }
+
+ // Increment the snapshot counter
+ uint256 snapshotId = nextSnapshotId;
+ nextSnapshotId += 1;
+ nextSnapshotModified = false;
+
+ // Log and return
+ SnapshotCreated(snapshotId);
+ return snapshotId;
+ }
+
+ function mNextSnapshotId()
+ internal
+ returns (uint256)
+ {
+ uint256 dayBase = 2**128 * (block.timestamp / 1 days);
+
+ // New day has started
+ if (dayBase > nextSnapshotId) {
+ nextSnapshotId = dayBase + 1;
+ nextSnapshotModified = false;
+
+ SnapshotCreated(dayBase);
+ return nextSnapshotId;
+ }
+
+ // Within same day
+ return nextSnapshotId;
+ }
+
+ function mFlagSnapshotModified()
+ internal
+ {
+ if (!nextSnapshotModified) {
+ nextSnapshotModified = true;
+ }
+ }
+}
diff --git a/contracts/Snapshot/EveryBlock.sol b/contracts/Snapshot/EveryBlock.sol
new file mode 100644
index 00000000..e311b73b
--- /dev/null
+++ b/contracts/Snapshot/EveryBlock.sol
@@ -0,0 +1,18 @@
+pragma solidity ^0.4.13;
+
+import './MPolicy.sol';
+
+contract EveryBlock is MPolicy {
+
+ function mNextSnapshotId()
+ internal
+ returns (uint256)
+ {
+ return block.number;
+ }
+
+ function mFlagSnapshotModified()
+ internal
+ {
+ }
+}
diff --git a/contracts/Snapshot/MPolicy.sol b/contracts/Snapshot/MPolicy.sol
new file mode 100644
index 00000000..fd7e2970
--- /dev/null
+++ b/contracts/Snapshot/MPolicy.sol
@@ -0,0 +1,23 @@
+pragma solidity ^0.4.13;
+
+// Mixin for the snapshot policy
+contract MPolicy {
+
+////////////////
+// Internal abstract functions
+////////////////
+
+ // The snapshot Ids need to be monotonically increasing.
+ // Whenever the snaspshot id changes, a new snapshot will
+ // be created. As long as the same value is being returned,
+ // this snapshot will be updated.
+ //
+ // Values passed to `hasValueAt` and `valuteAt` are required
+ // to be strictly less than `mixinNextSnapshotId()`.
+ function mNextSnapshotId()
+ internal
+ returns (uint256);
+
+ function mFlagSnapshotModified()
+ internal;
+}
diff --git a/contracts/Snapshot/Snapshot.sol b/contracts/Snapshot/Snapshot.sol
new file mode 100644
index 00000000..a18e3436
--- /dev/null
+++ b/contracts/Snapshot/Snapshot.sol
@@ -0,0 +1,173 @@
+pragma solidity ^0.4.13;
+
+import './MPolicy.sol';
+
+// Snapshot consumes MPolicy
+contract Snapshot is MPolicy {
+
+////////////////
+// Types
+////////////////
+
+ /// @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 Values {
+
+ // `fromBlock` is the block number that the value was generated from
+ uint256 snapshot;
+
+ // `value` is the amount of tokens at a specific block number
+ uint256 value;
+ }
+
+////////////////
+// Internal functions
+////////////////
+
+ function hasValue(
+ Values[] storage values
+ )
+ internal
+ constant
+ returns (bool)
+ {
+ return values.length > 0;
+ }
+
+ function hasValueAt(
+ Values[] storage values,
+ uint _snapshot
+ )
+ internal
+ constant
+ returns (bool)
+ {
+ require(_snapshot < mNextSnapshotId());
+ return values.length > 0 && values[0].snapshot <= _snapshot;
+ }
+
+ function getValue(
+ Values[] storage values,
+ uint _defaultValue
+ )
+ internal
+ constant
+ returns (uint)
+ {
+ if (values.length == 0) {
+ return _defaultValue;
+ } else {
+ uint last = values.length - 1;
+ return values[last].value;
+ }
+ }
+
+ /// @dev `getValueAt` retrieves the number of tokens at a given block number
+ /// @param values The history of values being queried
+ /// @param _snapshot The block number to retrieve the value at
+ /// @return The number of tokens being queried
+ function getValueAt(
+ Values[] storage values,
+ uint _snapshot,
+ uint _defaultValue
+ )
+ internal
+ constant
+ returns (uint)
+ {
+ require(_snapshot < mNextSnapshotId());
+
+ // Empty value
+ if (values.length == 0) {
+ return _defaultValue;
+ }
+
+ // Shortcut for the out of bounds snapshots
+ uint last = values.length - 1;
+ uint lastSnapshot = values[last].snapshot;
+ if (_snapshot >= lastSnapshot) {
+ return values[last].value;
+ }
+ uint firstSnapshot = values[0].snapshot;
+ if (_snapshot < firstSnapshot) {
+ return _defaultValue;
+ }
+
+ // Binary search of the value in the array
+ uint min = 0;
+ uint max = last;
+ while (max > min) {
+ uint mid = (max + min + 1) / 2;
+ if (values[mid].snapshot <= _snapshot) {
+ min = mid;
+ } else {
+ max = mid - 1;
+ }
+ }
+ return values[min].value;
+ }
+
+ /// @dev `setValue` used to update the `balances` map and the
+ /// `totalSupplyHistory`
+ /// @param values The history of data being updated
+ /// @param _value The new number of tokens
+ function setValue(
+ Values[] storage values,
+ uint256 _value
+ )
+ internal
+ {
+ // TODO: simplify or break into smaller functions
+
+ uint256 nextSnapshot = mNextSnapshotId();
+
+ // Always create a new entry if there currently is no value
+ bool empty = values.length == 0;
+ if (empty) {
+
+ // Create a new entry
+ values.push(Values({
+ snapshot: nextSnapshot,
+ value: _value
+ }));
+
+ // Flag next snapshot as modified
+ mFlagSnapshotModified();
+ return;
+ }
+
+ uint last = values.length - 1;
+ bool frozen = values[last].snapshot < nextSnapshot;
+ if (frozen) {
+
+ // Do nothing if the value was not modified
+ bool unmodified = values[last].value == _value;
+ if (unmodified) {
+ return;
+ }
+
+ // Create new entry
+ values.push(Values({
+ snapshot: nextSnapshot,
+ value: _value
+ }));
+
+ // Flag next snapshot as modified
+ mFlagSnapshotModified();
+
+ } else { // We are updating the nextSnapshot
+
+ bool unmodifiedd = last > 0 && values[last - 1].value == _value;
+ if (unmodifiedd) {
+ // Remove nextSnapshot entry
+ delete values[last];
+ values.length--;
+ return;
+ }
+
+ // Overwrite next snapshot entry
+ values[last].value = _value;
+ }
+ }
+}
diff --git a/contracts/Snapshot/Snapshotable.sol b/contracts/Snapshot/Snapshotable.sol
new file mode 100644
index 00000000..fe1fad2c
--- /dev/null
+++ b/contracts/Snapshot/Snapshotable.sol
@@ -0,0 +1,63 @@
+pragma solidity ^0.4.13;
+
+import '../Standards/ISnapshotable.sol';
+import './MPolicy.sol';
+
+contract Snapshotable is
+ MPolicy,
+ ISnapshotable
+{
+
+ uint256 nextSnapshotId;
+ bool nextSnapshotModified;
+
+ function SnapshotOndemand(uint256 start)
+ internal
+ {
+ nextSnapshotId = start;
+ nextSnapshotModified = true;
+ }
+
+ function createSnapshot()
+ public
+ returns (uint256)
+ {
+ require(nextSnapshotId < 2**256 - 1);
+
+ // If the snapshot was not modified, return
+ // the previous snapshot id. Their states
+ // are identical.
+ if (!nextSnapshotModified) {
+ uint256 previousSnapshot = nextSnapshotId - 1;
+
+ // Log the event anyway, some logic may depend
+ // depend on it.
+ SnapshotCreated(previousSnapshot);
+ return previousSnapshot;
+ }
+
+ // Increment the snapshot counter
+ uint256 snapshotId = nextSnapshotId;
+ nextSnapshotId += 1;
+ nextSnapshotModified = false;
+
+ // Log and return
+ SnapshotCreated(snapshotId);
+ return snapshotId;
+ }
+
+ function mixinNextSnapshotId()
+ internal
+ returns (uint256)
+ {
+ return nextSnapshotId;
+ }
+
+ function mixinFlagSnapshotModified()
+ internal
+ {
+ if (!nextSnapshotModified) {
+ nextSnapshotModified = true;
+ }
+ }
+}
diff --git a/contracts/SnapshotToken.sol b/contracts/SnapshotToken.sol
new file mode 100644
index 00000000..ec081df9
--- /dev/null
+++ b/contracts/SnapshotToken.sol
@@ -0,0 +1,257 @@
+pragma solidity ^0.4.13;
+
+import './Controlled.sol';
+import './ControllerClaims.sol';
+import './Helpers/Allowance.sol';
+import './Helpers/MMint.sol';
+import './Helpers/TokenInfo.sol';
+import './IsContract.sol';
+import './ITokenController.sol';
+import './Snapshot/DailyAndSnapshotable.sol';
+import './Standards/IApproveAndCallFallback.sol';
+import './Standards/IERC20Token.sol';
+import './Standards/ISnapshotToken.sol';
+import './Standards/ISnapshotTokenParent.sol';
+import { SnapshotToken as SnapshotTokenBase } from './Helpers/SnapshotToken.sol';
+
+/*
+ Copyright 2016, Remco Bloemen, 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 SnapshotToken Contract
+/// @author Remco Bloemen, 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 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"
+
+// Consumes the MMint mixin from SnapshotToken
+contract SnapshotToken is
+ IERC20Token,
+ ISnapshotToken,
+ MMint,
+ SnapshotTokenBase,
+ DailyAndSnapshotable,
+ Allowance,
+ TokenInfo,
+ Controlled,
+ ControllerClaims,
+ IsContract
+{
+
+ string private constant VERSION = "ST_1.0";
+
+ // Flag that determines if the token is transferable or not.
+ bool public transfersEnabled;
+
+////////////////
+// Constructor
+////////////////
+
+ /// @notice Constructor to create a MiniMeToken
+ /// @param parentToken Address of the parent token, set to 0x0 if it is a
+ /// new token
+ /// @param parentSnapshot 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 SnapshotToken(
+ ISnapshotTokenParent parentToken,
+ uint parentSnapshot,
+ string tokenName,
+ uint8 decimalUnits,
+ string tokenSymbol,
+ bool _transfersEnabled
+ )
+ SnapshotTokenBase(parentToken, parentSnapshot)
+ DailyAndSnapshotable()
+ Allowance()
+ TokenInfo(tokenName, decimalUnits, tokenSymbol, VERSION)
+ Controlled()
+ ControllerClaims()
+ {
+ transfersEnabled = _transfersEnabled;
+ }
+
+////////////////
+// Fallback
+////////////////
+
+ /// @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 ()
+ public
+ payable
+ {
+ require(isContract(controller));
+ require(controller.proxyPayment.value(msg.value)(msg.sender));
+ }
+
+///////////////////
+// Public functions
+///////////////////
+
+ /// @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
+ /// Overrides the public function in SnapshotTokenBase
+ function transfer(address _to, uint256 _amount)
+ public
+ returns (bool success)
+ {
+ return transfer(msg.sender, _to, _amount);
+ }
+
+ /// @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
+ /// Overrides the public function in AllowanceBase
+ function approve(address _spender, uint256 _amount)
+ public
+ returns (bool success)
+ {
+ require(transfersEnabled);
+
+ // Alerts the token controller of the approve function call
+ if (isContract(controller)) {
+ require(controller.onApprove(msg.sender, _spender, _amount));
+ }
+
+ return Allowance.approve(_spender, _amount);
+ }
+
+ /// @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
+ /// Overrides the public function in AllowanceBase
+ function approveAndCall(address _spender, uint256 _amount, bytes _extraData)
+ public
+ returns (bool success)
+ {
+ require(approve(_spender, _amount));
+
+ IApproveAndCallFallback(_spender).receiveApproval(
+ msg.sender,
+ _amount,
+ this,
+ _extraData
+ );
+
+ 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)
+ public
+ onlyController
+ {
+ transfersEnabled = _transfersEnabled;
+ }
+
+////////////////
+// Generate and destroy tokens
+////////////////
+
+ /// @notice Mints `_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)
+ public
+ onlyController
+ returns (bool)
+ {
+ return SnapshotTokenBase.mGenerateTokens(_owner, _amount);
+ }
+
+ /// @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)
+ public
+ onlyController
+ returns (bool)
+ {
+ return SnapshotTokenBase.mDestroyTokens(_owner, _amount);
+ }
+
+////////////////
+// Internal functions
+////////////////
+
+ /// @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
+ /// Implements the abstract function from AllowanceBase
+ function mAllowanceTransfer(address _from, address _to, uint _amount)
+ internal
+ returns(bool)
+ {
+ return transfer(_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
+ /// Implements the abstract function from AllowanceBase
+ function transfer(address _from, address _to, uint _amount)
+ internal
+ returns(bool)
+ {
+ require(transfersEnabled);
+
+ // Alerts the token controller of the transfer
+ if (isContract(controller)) {
+ require(controller.onTransfer(_from, _to, _amount));
+ }
+
+ // Do not allow transfer to 0x0 or the token contract itself
+ require(_to != 0);
+ require(_to != address(this));
+
+ return mTransfer(_from, _to, _amount);
+ }
+}
diff --git a/contracts/Standards/IApproveAndCallFallback.sol b/contracts/Standards/IApproveAndCallFallback.sol
new file mode 100644
index 00000000..34e5b55f
--- /dev/null
+++ b/contracts/Standards/IApproveAndCallFallback.sol
@@ -0,0 +1,15 @@
+pragma solidity ^0.4.13;
+
+import './IERC20Token.sol';
+
+contract IApproveAndCallFallback {
+
+ function receiveApproval(
+ address from,
+ uint256 amount,
+ IERC20Token token,
+ bytes data
+ )
+ public;
+
+}
diff --git a/contracts/Standards/IBasicToken.sol b/contracts/Standards/IBasicToken.sol
new file mode 100644
index 00000000..591813e6
--- /dev/null
+++ b/contracts/Standards/IBasicToken.sol
@@ -0,0 +1,38 @@
+pragma solidity ^0.4.13;
+
+
+contract IBasicToken {
+
+////////////////
+// Events
+////////////////
+
+ event Transfer(address indexed _from, address indexed _to, uint256 _amount);
+
+///////////////////
+// ERC20 Basic Methods
+///////////////////
+
+ /// @dev This function makes it easy to get the total number of tokens
+ /// @return The total number of tokens
+ function totalSupply()
+ public
+ constant
+ returns (uint);
+
+ /// @param _owner The address that's balance is being requested
+ /// @return The balance of `_owner` at the current block
+ function balanceOf(address _owner)
+ public
+ constant
+ returns (uint256 balance);
+
+ /// @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)
+ public
+ returns (bool success);
+
+}
diff --git a/contracts/Standards/IERC20Allowance.sol b/contracts/Standards/IERC20Allowance.sol
new file mode 100644
index 00000000..d7d42e79
--- /dev/null
+++ b/contracts/Standards/IERC20Allowance.sol
@@ -0,0 +1,49 @@
+pragma solidity ^0.4.13;
+
+
+// is IBasicToken
+contract IERC20Allowance {
+
+ /// @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)
+ public
+ constant
+ returns (uint256 remaining);
+
+ /// @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)
+ public
+ returns (bool success);
+
+ /// @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)
+ public
+ returns (bool success);
+
+
+ /// @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)
+ public
+ returns (bool success);
+
+}
diff --git a/contracts/Standards/IERC20Token.sol b/contracts/Standards/IERC20Token.sol
new file mode 100644
index 00000000..016dc48f
--- /dev/null
+++ b/contracts/Standards/IERC20Token.sol
@@ -0,0 +1,81 @@
+pragma solidity ^0.4.13;
+
+
+// is IBasicToken, IERC20Allowance
+contract IERC20Token {
+
+////////////////
+// Events
+////////////////
+
+ event Transfer(address indexed _from, address indexed _to, uint256 _amount);
+
+///////////////////
+// ERC20 Basic Methods
+///////////////////
+
+ /// @dev This function makes it easy to get the total number of tokens
+ /// @return The total number of tokens
+ function totalSupply()
+ public
+ constant
+ returns (uint);
+
+ /// @param _owner The address that's balance is being requested
+ /// @return The balance of `_owner` at the current block
+ function balanceOf(address _owner)
+ public
+ constant
+ returns (uint256 balance);
+
+ /// @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)
+ public
+ returns (bool success);
+
+ /// @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)
+ public
+ constant
+ returns (uint256 remaining);
+
+ /// @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)
+ public
+ returns (bool success);
+
+ /// @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)
+ public
+ returns (bool success);
+
+
+ /// @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)
+ public
+ returns (bool success);
+
+}
diff --git a/contracts/Standards/ISnapshotToken.sol b/contracts/Standards/ISnapshotToken.sol
new file mode 100644
index 00000000..c7f6a1c9
--- /dev/null
+++ b/contracts/Standards/ISnapshotToken.sol
@@ -0,0 +1,61 @@
+pragma solidity ^0.4.13;
+
+// is ISnapshotable, IBasicToken, ISnapshotTokenParent
+contract ISnapshotToken {
+
+////////////////
+// Events
+////////////////
+
+ event SnapshotCreated(uint256 snapshot);
+
+ event Transfer(address indexed _from, address indexed _to, uint256 _amount);
+
+////////////////
+// Public functions
+////////////////
+
+ function createSnapshot()
+ public
+ returns (uint256);
+
+ /// @dev This function makes it easy to get the total number of tokens
+ /// @return The total number of tokens
+ function totalSupply()
+ public
+ constant
+ returns (uint);
+
+ /// @param _owner The address that's balance is being requested
+ /// @return The balance of `_owner` at the current block
+ function balanceOf(address _owner)
+ public
+ constant
+ returns (uint256 balance);
+
+ /// @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)
+ public
+ returns (bool success);
+
+ /// @notice Total amount of tokens at a specific `_snapshot`.
+ /// @param _snapshot The block number when the totalSupply is queried
+ /// @return The total amount of tokens at `_snapshot`
+ function totalSupplyAt(uint _snapshot)
+ public
+ constant
+ returns(uint);
+
+ /// @dev Queries the balance of `_owner` at a specific `_snapshot`
+ /// @param _owner The address from which the balance will be retrieved
+ /// @param _snapshot The block number when the balance is queried
+ /// @return The balance at `_snapshot`
+ function balanceOfAt(address _owner, uint _snapshot)
+ public
+ constant
+ returns (uint);
+
+}
diff --git a/contracts/Standards/ISnapshotTokenParent.sol b/contracts/Standards/ISnapshotTokenParent.sol
new file mode 100644
index 00000000..66828f66
--- /dev/null
+++ b/contracts/Standards/ISnapshotTokenParent.sol
@@ -0,0 +1,21 @@
+pragma solidity ^0.4.13;
+
+contract ISnapshotTokenParent {
+
+ /// @notice Total amount of tokens at a specific `_snapshot`.
+ /// @param _snapshot The block number when the totalSupply is queried
+ /// @return The total amount of tokens at `_snapshot`
+ function totalSupplyAt(uint _snapshot)
+ public
+ constant
+ returns(uint);
+
+ /// @dev Queries the balance of `_owner` at a specific `_snapshot`
+ /// @param _owner The address from which the balance will be retrieved
+ /// @param _snapshot The block number when the balance is queried
+ /// @return The balance at `_snapshot`
+ function balanceOfAt(address _owner, uint _snapshot)
+ public
+ constant
+ returns (uint);
+}
diff --git a/contracts/Standards/ISnapshotable.sol b/contracts/Standards/ISnapshotable.sol
new file mode 100644
index 00000000..47edc8f2
--- /dev/null
+++ b/contracts/Standards/ISnapshotable.sol
@@ -0,0 +1,19 @@
+pragma solidity ^0.4.13;
+
+contract ISnapshotable {
+
+////////////////
+// Events
+////////////////
+
+ event SnapshotCreated(uint256 snapshot);
+
+////////////////
+// Public functions
+////////////////
+
+ function createSnapshot()
+ public
+ returns (uint256);
+
+}
diff --git a/package.json b/package.json
index f2c548ee..b541fd12 100644
--- a/package.json
+++ b/package.json
@@ -1,47 +1,46 @@
{
- "name": "minimetoken",
- "version": "0.1.7",
- "description": "MiniMe contract",
- "main": "dist/minimetoken.js",
- "directories": {
- "test": "test"
- },
- "scripts": {
- "test": "mocha --compilers js:babel-core/register",
- "build": "rm -rf dist/* && babel-node js/compile.js && babel js/minimetoken.js -o dist/minimetoken.js"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/Giveth/minime.git"
- },
- "keywords": [
- "dao",
- "solidity",
- "token",
- "charity",
- "smart",
- "contract",
- "minime",
- "giveth",
- "ethereum"
- ],
- "author": "Jordi Baylina",
- "license": "GPL-3.0",
- "bugs": {
- "url": "https://github.com/Giveth/minimi/issues"
- },
- "homepage": "https://github.com/Giveth/minime",
- "dependencies": {
- "async": "^2.1.4",
- "bignumber.js": "^4.0.0",
- "ethconnector": "0.0.24",
- "lodash": "^4.17.4",
- "runethtx": "0.0.7"
- },
- "devDependencies": {
- "babel-cli": "^6.22.2",
- "babel-plugin-add-module-exports": "^0.2.1",
- "babel-preset-es2015": "^6.22.0",
- "babel-preset-stage-2": "^6.22.0"
- }
+ "name": "snapshottoken",
+ "version": "0.1.2",
+ "description": "SnapshotToken contract",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "test": "mocha --compilers js:babel-core/register",
+ "build": "rm -rf dist/* && babel-node js/compile.js && babel js/minimetoken.js -o dist/minimetoken.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Neufund/snapshottoken.git"
+ },
+ "keywords": [
+ "dao",
+ "solidity",
+ "token",
+ "charity",
+ "smart",
+ "contract",
+ "minime",
+ "giveth",
+ "ethereum"
+ ],
+ "author": "Remco Bloemen, Jordi Baylina",
+ "license": "GPL-3.0",
+ "bugs": {
+ "url": "https://github.com/Neufund/snapshottoken/issues"
+ },
+ "homepage": "https://github.com/Neufund/snapshottoken",
+ "dependencies": {
+ "async": "^2.1.4",
+ "bignumber.js": "^4.0.0",
+ "ethconnector": "0.0.24",
+ "lodash": "^4.17.4",
+ "runethtx": "0.0.7"
+ },
+ "devDependencies": {
+ "babel-cli": "^6.22.2",
+ "babel-plugin-add-module-exports": "^0.2.1",
+ "babel-preset-es2015": "^6.22.0",
+ "babel-preset-stage-2": "^6.22.0"
+ }
}