Major comment changes

This commit is contained in:
Griff Green 2017-01-01 16:11:02 +07:00 committed by GitHub
parent 29320c87e0
commit 274a3e0ae7
1 changed files with 78 additions and 32 deletions

View File

@ -19,29 +19,33 @@ pragma solidity ^0.4.6;
/// @title MiniMeToken Contract /// @title MiniMeToken Contract
/// @author Jordi Baylina /// @author Jordi Baylina
/// @dev This token contract's goal is to make it easy to clone this token and /// @dev This token contract's goal is to make it easy for anyone to clone this
/// spawn new tokens using the token distribution at a given block. /// 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 It is ERC20 compliant, but still needs to under go further testing.
// The controller must implement this interface /// @dev The token controller contract must implement these functions
contract TokenController { contract TokenController {
/// @notice Called when `_owner` sends ether to the MiniMe Token contract /// @notice Called when `_owner` sends ether to the MiniMe Token contract
/// @param _owner The address that sent the ether /// @param _owner The address that sent the ether to create tokens
/// @return True if the ether is accepted, false if it throws /// @return True if the ether is accepted, false if it throws
function proxyPayment(address _owner) payable returns(bool); function proxyPayment(address _owner) payable returns(bool);
/// @notice Notifies the controller about a transfer /// @notice Notifies the controller about a token transfer allowing the
/// controller to react if desired
/// @param _from The origin of the transfer /// @param _from The origin of the transfer
/// @param _to The destination of the transfer /// @param _to The destination of the transfer
/// @param _amount The amount of the transfer /// @param _amount The amount of the transfer
/// @return False if the controller does not authorize the transfer /// @return False if the controller does not authorize the transfer
function onTransfer(address _from, address _to, uint _amount) returns(bool); function onTransfer(address _from, address _to, uint _amount) returns(bool);
/// @notice Notifies the controller about an approval /// @notice Notifies the controller about an approval allowing the
/// controller to react if desired
/// @param _owner The address that calls `approve()` /// @param _owner The address that calls `approve()`
/// @param _spender The spender in the `approve()` call /// @param _spender The spender in the `approve()` call
/// @param _amount The ammount in the `approve()` call /// @param _amount The amount in the `approve()` call
/// @return False if the controller does not authorize the approval /// @return False if the controller does not authorize the approval
function onApprove(address _owner, address _spender, uint _amount) function onApprove(address _owner, address _spender, uint _amount)
returns(bool); returns(bool);
@ -63,6 +67,9 @@ contract Controlled {
} }
} }
/// @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 { contract MiniMeToken is Controlled {
string public name; //The Token's name: e.g. DigixDAO Tokens string public name; //The Token's name: e.g. DigixDAO Tokens
@ -71,8 +78,9 @@ contract MiniMeToken is Controlled {
string public version = 'MMT_0.1'; //An arbitrary versioning scheme string public version = 'MMT_0.1'; //An arbitrary versioning scheme
/// @dev `Checkpoint` is the structure that attaches a block number to the a /// @dev `Checkpoint` is the structure that attaches a block number to a
/// given value /// given value, the block number attached is the one that last changed the
/// value
struct Checkpoint { struct Checkpoint {
// `fromBlock` is the block number that the value was generated from // `fromBlock` is the block number that the value was generated from
@ -86,14 +94,16 @@ contract MiniMeToken is Controlled {
// it will be 0x0 for a token that was not cloned // it will be 0x0 for a token that was not cloned
MiniMeToken public parentToken; MiniMeToken public parentToken;
// `parentSnapShotBlock` is the Block number from the Parent Token that was // `parentSnapShotBlock` is the block number from the Parent Token that was
// used to determine the initial distribution of the Clone Token // used to determine the initial distribution of the Clone Token
uint public parentSnapShotBlock; uint public parentSnapShotBlock;
// `creationBlock` is the block number that the Clone Token was created // `creationBlock` is the block number that the Clone Token was created
uint public creationBlock; uint public creationBlock;
// `balances` is the map that tracks the balance of each address // `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; mapping (address => Checkpoint[]) balances;
// `allowed` tracks any extra transfer rights as in all ERC20 tokens // `allowed` tracks any extra transfer rights as in all ERC20 tokens
@ -114,7 +124,8 @@ contract MiniMeToken is Controlled {
/// @notice Constructor to create a MiniMeToken /// @notice Constructor to create a MiniMeToken
/// @param _tokenFactory The address of the MiniMeTokenFactory contract that /// @param _tokenFactory The address of the MiniMeTokenFactory contract that
/// will create the Clone token contracts /// 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 /// @param _parentToken Address of the parent token, set to 0x0 if it is a
/// new token /// new token
/// @param _parentSnapShotBlock Block of the parent token that will /// @param _parentSnapShotBlock Block of the parent token that will
@ -166,10 +177,10 @@ contract MiniMeToken is Controlled {
function transferFrom(address _from, address _to, uint256 _amount function transferFrom(address _from, address _to, uint256 _amount
) returns (bool success) { ) returns (bool success) {
// The controller of this contract can move tokens around at will, this /// @dev The controller of this contract can move tokens around at will,
// is important to recognize! Confirm that you trust the controller of /// this is important to recognize! Confirm that you trust the
// this contract, which in most situations should be another open /// controller of this contract, which in most situations should be
// source smart contract or 0x0 /// another open source smart contract or 0x0
if (msg.sender != controller) { if (msg.sender != controller) {
if (!transfersEnabled) throw; if (!transfersEnabled) throw;
@ -180,6 +191,12 @@ contract MiniMeToken is Controlled {
return doTransfer(_from, _to, _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 function doTransfer(address _from, address _to, uint _amount
) internal returns(bool) { ) internal returns(bool) {
@ -197,6 +214,7 @@ contract MiniMeToken is Controlled {
return false; return false;
} }
// Alerts the token controller of the transfer
if ((controller != 0)&&(isContract(controller))) { if ((controller != 0)&&(isContract(controller))) {
if (!TokenController(controller).onTransfer(_from, _to, _amount)) if (!TokenController(controller).onTransfer(_from, _to, _amount))
throw; throw;
@ -224,7 +242,8 @@ contract MiniMeToken is Controlled {
} }
/// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
/// its behalf /// 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 _spender The address of the account able to transfer the tokens
/// @param _amount The amount of tokens to be approved for transfer /// @param _amount The amount of tokens to be approved for transfer
/// @return True if the approval was successful /// @return True if the approval was successful
@ -232,10 +251,12 @@ contract MiniMeToken is Controlled {
if (!transfersEnabled) throw; if (!transfersEnabled) throw;
// To change the approve amount you first have to reduce the addresses´ // To change the approve amount you first have to reduce the addresses´
// allowance to zero by calling `approve(_spender,0)` if it is not // allowance to zero by calling `approve(_spender,0)` if it is not
// already 0 https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 // already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
if ((_amount!=0) && (allowed[msg.sender][_spender] !=0)) throw; if ((_amount!=0) && (allowed[msg.sender][_spender] !=0)) throw;
// Alerts the token controller of the approve function call
if ((controller != 0)&&(isContract(controller))) { if ((controller != 0)&&(isContract(controller))) {
if (!TokenController(controller).onApprove(msg.sender, _spender, _amount)) if (!TokenController(controller).onApprove(msg.sender, _spender, _amount))
throw; throw;
@ -246,6 +267,7 @@ contract MiniMeToken is Controlled {
return true; 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 _owner The address of the account that owns the token
/// @param _spender The address of the account able to transfer the tokens /// @param _spender The address of the account able to transfer the tokens
/// @return Amount of remaining tokens of _owner that _spender is allowed /// @return Amount of remaining tokens of _owner that _spender is allowed
@ -257,7 +279,8 @@ contract MiniMeToken is Controlled {
/// @notice `msg.sender` approves `_spender` to send `_amount` tokens on /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
/// its behalf, and then a function is triggered in the contract that is /// its behalf, and then a function is triggered in the contract that is
/// being approved, `_spender` /// 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 _spender The address of the contract able to transfer the tokens
/// @param _amount The amount of tokens to be approved for transfer /// @param _amount The amount of tokens to be approved for transfer
/// @return True if the function call was successful /// @return True if the function call was successful
@ -271,7 +294,7 @@ contract MiniMeToken is Controlled {
// is being approved (`_spender`). The function should look like: // is being approved (`_spender`). The function should look like:
// `receiveApproval(address _from, uint256 _amount, address // `receiveApproval(address _from, uint256 _amount, address
// _tokenContract, bytes _extraData)` It is assumed that the call // _tokenContract, bytes _extraData)` It is assumed that the call
// *should* succeed, otherwise one would use vanilla approve instead. // *should* succeed, otherwise the plain vanilla approve would be used
if(!_spender.call( if(!_spender.call(
bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))),
msg.sender, msg.sender,
@ -283,7 +306,8 @@ contract MiniMeToken is Controlled {
return true; return true;
} }
/// @return The total amount of tokens /// @dev This function makes it easy to get the total number of tokens
/// @return The total number of tokens
function totalSupply() constant returns (uint) { function totalSupply() constant returns (uint) {
return totalSupplyAt(block.number); return totalSupplyAt(block.number);
} }
@ -293,7 +317,7 @@ contract MiniMeToken is Controlled {
// Query balance and totalSupply in History // Query balance and totalSupply in History
//////////////// ////////////////
/// @notice Queries the balance of `_owner` at a specific `_blockNumber` /// @dev Queries the balance of `_owner` at a specific `_blockNumber`
/// @param _owner The address from which the balance will be retrieved /// @param _owner The address from which the balance will be retrieved
/// @param _blockNumber The block number when the balance is queried /// @param _blockNumber The block number when the balance is queried
/// @return The balance at `_blockNumber` /// @return The balance at `_blockNumber`
@ -321,7 +345,7 @@ contract MiniMeToken is Controlled {
// This will return the expected balance during normal situations // This will return the expected balance during normal situations
} else { } else {
return getValueAt( balances[_owner], _blockNumber); return getValueAt(balances[_owner], _blockNumber);
} }
} }
@ -351,7 +375,7 @@ contract MiniMeToken is Controlled {
// This will return the expected totalSupply during normal situations // This will return the expected totalSupply during normal situations
} else { } else {
return getValueAt( totalSupplyHistory, _blockNumber); return getValueAt(totalSupplyHistory, _blockNumber);
} }
} }
@ -362,7 +386,7 @@ contract MiniMeToken is Controlled {
/// @notice Creates a new clone token with the initial distribution being /// @notice Creates a new clone token with the initial distribution being
/// this token at `_snapshotBlock` /// this token at `_snapshotBlock`
/// @param _cloneTokenName Name of the clone token /// @param _cloneTokenName Name of the clone token
/// @param _cloneDecimalUnits Units of the clone token /// @param _cloneDecimalUnits Number of decimals of the smallest unit
/// @param _cloneTokenSymbol Symbol of the clone token /// @param _cloneTokenSymbol Symbol of the clone token
/// @param _snapshotBlock Block when the distribution of the parent token is /// @param _snapshotBlock Block when the distribution of the parent token is
/// copied to set the initial distribution of the new clone token; /// copied to set the initial distribution of the new clone token;
@ -443,9 +467,14 @@ contract MiniMeToken is Controlled {
// Internal helper functions to query and set a value in a snapshot array // 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 function getValueAt(Checkpoint[] storage checkpoints, uint _block
) constant internal returns (uint) { ) constant internal returns (uint) {
if (checkpoints.length == 0) return 0; if (checkpoints.length == 0) return 0;
// Shortcut for the actual value // Shortcut for the actual value
if (_block >= checkpoints[checkpoints.length-1].fromBlock) if (_block >= checkpoints[checkpoints.length-1].fromBlock)
return checkpoints[checkpoints.length-1].value; return checkpoints[checkpoints.length-1].value;
@ -465,6 +494,10 @@ contract MiniMeToken is Controlled {
return checkpoints[min].value; 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 function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value
) internal { ) internal {
if ((checkpoints.length == 0) if ((checkpoints.length == 0)
@ -478,7 +511,9 @@ contract MiniMeToken is Controlled {
} }
} }
// Internal function to determine if an address is a cntract /// @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) { function isContract(address _addr) constant internal returns(bool) {
uint size; uint size;
assembly { assembly {
@ -488,8 +523,8 @@ contract MiniMeToken is Controlled {
} }
/// @notice The fallback function: If the contract's controller has not been /// @notice The fallback function: If the contract's controller has not been
/// set to 0, the ether is sent to the controller (normally the token /// set to 0, then the `proxyPayment` method is called which relays the
/// creation contract) using the `proxyPayment` method. /// ether and creates tokens as described in the token controller contract
function () payable { function () payable {
if (controller == 0) throw; if (controller == 0) throw;
if (isContract(controller)) { if (isContract(controller)) {
@ -519,10 +554,21 @@ contract MiniMeToken is Controlled {
// MiniMeTokenFactory // MiniMeTokenFactory
//////////////// ////////////////
// This contract is used to generate clone contracts from a contract. /// @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 /// In solidity this is the way to create a contract from a contract of the
// class /// same class
contract MiniMeTokenFactory { 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( function createCloneToken(
address _parentToken, address _parentToken,
uint _snapshotBlock, uint _snapshotBlock,