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" + } }