Merge remote-tracking branch 'origin/minimetoken' into 150-gas-abstraction

This commit is contained in:
Ricardo Guilherme Schmidt 2018-05-08 14:51:01 -03:00
commit 468b8c11c4
10 changed files with 428 additions and 340 deletions

View File

@ -10,7 +10,7 @@ contract Controlled {
address public controller; address public controller;
constructor() public { constructor() internal {
controller = msg.sender; controller = msg.sender;
} }

View File

@ -14,7 +14,7 @@ contract Owned {
address public owner; address public owner;
/// @notice The Constructor assigns the message sender to be `owner` /// @notice The Constructor assigns the message sender to be `owner`
constructor() public { constructor() internal {
owner = msg.sender; owner = msg.sender;
} }

View File

@ -1,5 +1,5 @@
pragma solidity ^0.4.14; pragma solidity ^0.4.23;
contract ApproveAndCallFallBack { contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 _amount, address _token, bytes _data) public ; function receiveApproval(address from, uint256 _amount, address _token, bytes _data) public;
} }

View File

@ -1,48 +1,52 @@
pragma solidity ^0.4.17; pragma solidity ^0.4.23;
// Abstract contract for the full ERC 20 Token standard // Abstract contract for the full ERC 20 Token standard
// https://github.com/ethereum/EIPs/issues/20 // https://github.com/ethereum/EIPs/issues/20
contract ERC20Token { interface ERC20Token {
/* This is a slight change to the ERC20 base standard.
function totalSupply() constant returns (uint256 supply); /**
is replaced with: * @notice send `_value` token to `_to` from `msg.sender`
uint256 public totalSupply; * @param _to The address of the recipient
This automatically creates a getter function for the totalSupply. * @param _value The amount of token to be transferred
This is moved to the base contract since public getter functions are not * @return Whether the transfer was successful or not
currently recognised as an implementation of the matching abstract
function by the compiler.
*/ */
/// total amount of tokens function transfer(address _to, uint256 _value) external returns (bool success);
uint256 public totalSupply;
/// @notice send `_value` token to `_to` from `msg.sender` /**
/// @param _to The address of the recipient * @notice `msg.sender` approves `_spender` to spend `_value` tokens
/// @param _value The amount of token to be transferred * @param _spender The address of the account able to transfer the tokens
/// @return Whether the transfer was successful or not * @param _value The amount of tokens to be approved for transfer
function transfer(address _to, uint256 _value) public returns (bool success); * @return Whether the approval was successful or not
*/
function approve(address _spender, uint256 _value) external returns (bool success);
/// @notice `msg.sender` approves `_spender` to spend `_value` tokens /**
/// @param _spender The address of the account able to transfer the tokens * @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
/// @param _value The amount of tokens to be approved for transfer * @param _from The address of the sender
/// @return Whether the approval was successful or not * @param _to The address of the recipient
function approve(address _spender, uint256 _value) public returns (bool success); * @param _value The amount of token to be transferred
* @return Whether the transfer was successful or not
*/
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` /**
/// @param _from The address of the sender * @param _owner The address from which the balance will be retrieved
/// @param _to The address of the recipient * @return The balance
/// @param _value The amount of token to be transferred */
/// @return Whether the transfer was successful or not function balanceOf(address _owner) external view returns (uint256 balance);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
/// @param _owner The address from which the balance will be retrieved /**
/// @return The balance * @param _owner The address of the account owning tokens
function balanceOf(address _owner) public view returns (uint256 balance); * @param _spender The address of the account able to transfer the tokens
* @return Amount of remaining tokens allowed to spent
*/
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
/// @param _owner The address of the account owning tokens /**
/// @param _spender The address of the account able to transfer the tokens * @notice return total supply of tokens
/// @return Amount of remaining tokens allowed to spent */
function allowance(address _owner, address _spender) public view returns (uint256 remaining); function totalSupply() external view returns (uint256 supply);
event Transfer(address indexed _from, address indexed _to, uint256 _value); event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value);

View File

@ -1,4 +1,4 @@
pragma solidity ^0.4.6; pragma solidity ^0.4.23;
/* /*
Copyright 2016, Jordi Baylina Copyright 2016, Jordi Baylina
@ -16,14 +16,15 @@ pragma solidity ^0.4.6;
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/**
/// @title MiniMeToken Contract * @title MiniMeToken Contract
/// @author Jordi Baylina * @author Jordi Baylina
/// @dev This token contract's goal is to make it easy for anyone to clone this * @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 * 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 * and DApps to upgrade their features in a decentralized manner without
/// affecting the original token * 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.
*/
import "../common/Controlled.sol"; import "../common/Controlled.sol";
import "./TokenController.sol"; import "./TokenController.sol";
@ -31,9 +32,11 @@ import "./ApproveAndCallFallBack.sol";
import "./MiniMeTokenInterface.sol"; import "./MiniMeTokenInterface.sol";
import "./MiniMeTokenFactory.sol"; import "./MiniMeTokenFactory.sol";
/// @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 * @dev The actual token contract, the default controller is the msg.sender
/// token controller contract, which Giveth will call a "Campaign" * 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 MiniMeTokenInterface, Controlled { contract MiniMeToken is MiniMeTokenInterface, Controlled {
string public name; //The Token's name: e.g. DigixDAO Tokens string public name; //The Token's name: e.g. DigixDAO Tokens
@ -41,10 +44,11 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
string public symbol; //An identifier: e.g. REP string public symbol; //An identifier: e.g. REP
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 a * @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 * given value, the block number attached is the one that last changed the
/// value * 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,20 +90,22 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// Constructor // Constructor
//////////////// ////////////////
/// @notice Constructor to create a MiniMeToken /**
/// @param _tokenFactory The address of the MiniMeTokenFactory contract that * @notice Constructor to create a MiniMeToken
/// will create the Clone token contracts, the token factory needs to be * @param _tokenFactory The address of the MiniMeTokenFactory contract that
/// deployed first * will create the Clone token contracts, the token factory needs to be
/// @param _parentToken Address of the parent token, set to 0x0 if it is a * deployed first
/// new token * @param _parentToken Address of the parent token, set to 0x0 if it is a
/// @param _parentSnapShotBlock Block of the parent token that will * new token
/// determine the initial distribution of the clone token, set to 0 if it * @param _parentSnapShotBlock Block of the parent token that will
/// is a new token * determine the initial distribution of the clone token, set to 0 if it
/// @param _tokenName Name of the new token * is a new token
/// @param _decimalUnits Number of decimals of the new token * @param _tokenName Name of the new token
/// @param _tokenSymbol Token Symbol for the new token * @param _decimalUnits Number of decimals of the new token
/// @param _transfersEnabled If true, tokens will be able to be transferred * @param _tokenSymbol Token Symbol for the new token
function MiniMeToken( * @param _transfersEnabled If true, tokens will be able to be transferred
*/
constructor(
address _tokenFactory, address _tokenFactory,
address _parentToken, address _parentToken,
uint _parentSnapShotBlock, uint _parentSnapShotBlock,
@ -125,21 +131,25 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// ERC20 Methods // ERC20 Methods
/////////////////// ///////////////////
/// @notice Send `_amount` tokens to `_to` from `msg.sender` /**
/// @param _to The address of the recipient * @notice Send `_amount` tokens to `_to` from `msg.sender`
/// @param _amount The amount of tokens to be transferred * @param _to The address of the recipient
/// @return Whether the transfer was successful or not * @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) { function transfer(address _to, uint256 _amount) public returns (bool success) {
require(transfersEnabled); require(transfersEnabled);
return doTransfer(msg.sender, _to, _amount); return doTransfer(msg.sender, _to, _amount);
} }
/// @notice Send `_amount` tokens to `_to` from `_from` on the condition it /**
/// is approved by `_from` * @notice Send `_amount` tokens to `_to` from `_from` on the condition it
/// @param _from The address holding the tokens being transferred * is approved by `_from`
/// @param _to The address of the recipient * @param _from The address holding the tokens being transferred
/// @param _amount The amount of tokens to be transferred * @param _to The address of the recipient
/// @return True if the transfer was successful * @param _amount The amount of tokens to be transferred
* @return True if the transfer was successful
*/
function transferFrom( function transferFrom(
address _from, address _from,
address _to, address _to,
@ -165,12 +175,14 @@ contract MiniMeToken is MiniMeTokenInterface, 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. * @dev This is the actual transfer function in the token contract, it can
/// @param _from The address holding the tokens being transferred * only be called by other functions in this contract.
/// @param _to The address of the recipient * @param _from The address holding the tokens being transferred
/// @param _amount The amount of tokens to be transferred * @param _to The address of the recipient
/// @return True if the transfer was successful * @param _amount The amount of tokens to be transferred
* @return True if the transfer was successful
*/
function doTransfer( function doTransfer(
address _from, address _from,
address _to, address _to,
@ -191,7 +203,7 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// If the amount being transfered is more than the balance of the // If the amount being transfered is more than the balance of the
// account the transfer returns false // account the transfer returns false
var previousBalanceFrom = balanceOfAt(_from, block.number); uint256 previousBalanceFrom = balanceOfAt(_from, block.number);
if (previousBalanceFrom < _amount) { if (previousBalanceFrom < _amount) {
return false; return false;
} }
@ -207,79 +219,97 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// Then update the balance array with the new value for the address // Then update the balance array with the new value for the address
// receiving the tokens // receiving the tokens
var previousBalanceTo = balanceOfAt(_to, block.number); uint256 previousBalanceTo = balanceOfAt(_to, block.number);
require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
updateValueAtNow(balances[_to], previousBalanceTo + _amount); updateValueAtNow(balances[_to], previousBalanceTo + _amount);
// An event to make the transfer easy to find on the blockchain // An event to make the transfer easy to find on the blockchain
Transfer(_from, _to, _amount); emit Transfer(_from, _to, _amount);
return true; return true;
} }
/// @param _owner The address that's balance is being requested function doApprove(
/// @return The balance of `_owner` at the current block address _from,
function balanceOf(address _owner) public constant returns (uint256 balance) { address _spender,
return balanceOfAt(_owner, block.number); uint256 _amount
} )
internal
/// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on returns (bool)
/// 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) {
require(transfersEnabled); require(transfersEnabled);
// 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 to mitigate the race condition described here: // already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
require((_amount == 0) || (allowed[msg.sender][_spender] == 0)); require((_amount == 0) || (allowed[_from][_spender] == 0));
// Alerts the token controller of the approve function call // Alerts the token controller of the approve function call
if (isContract(controller)) { if (isContract(controller)) {
require(TokenController(controller).onApprove(msg.sender, _spender, _amount)); require(TokenController(controller).onApprove(_from, _spender, _amount));
} }
allowed[msg.sender][_spender] = _amount; allowed[_from][_spender] = _amount;
Approval(msg.sender, _spender, _amount); emit Approval(_from, _spender, _amount);
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 that's balance is being requested
/// @param _spender The address of the account able to transfer the tokens * @return The balance of `_owner` at the current block
/// @return Amount of remaining tokens of _owner that _spender is allowed */
/// to spend function balanceOf(address _owner) external view 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) external returns (bool success) {
doApprove(msg.sender, _spender, _amount);
}
/**
* @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( function allowance(
address _owner, address _owner,
address _spender address _spender
) )
public external
constant view
returns (uint256 remaining) returns (uint256 remaining)
{ {
return allowed[_owner][_spender]; return allowed[_owner][_spender];
} }
/**
/// @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`. This allows users to use their tokens to * being approved, `_spender`. This allows users to use their tokens to
/// interact with contracts in one function call instead of two * 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
*/
function approveAndCall( function approveAndCall(
address _spender, address _spender,
uint256 _amount, uint256 _amount,
bytes _extraData bytes _extraData
) )
public external
returns (bool success) returns (bool success)
{ {
require(approve(_spender, _amount)); require(doApprove(msg.sender, _spender, _amount));
ApproveAndCallFallBack(_spender).receiveApproval( ApproveAndCallFallBack(_spender).receiveApproval(
msg.sender, msg.sender,
@ -291,9 +321,11 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
return true; return true;
} }
/// @dev This function makes it easy to get the total number of tokens /**
/// @return The total number of tokens * @dev This function makes it easy to get the total number of tokens
function totalSupply() public constant returns (uint) { * @return The total number of tokens
*/
function totalSupply() external view returns (uint) {
return totalSupplyAt(block.number); return totalSupplyAt(block.number);
} }
@ -302,16 +334,18 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// Query balance and totalSupply in History // 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 * @dev Queries the balance of `_owner` at a specific `_blockNumber`
/// @param _blockNumber The block number when the balance is queried * @param _owner The address from which the balance will be retrieved
/// @return The balance at `_blockNumber` * @param _blockNumber The block number when the balance is queried
* @return The balance at `_blockNumber`
*/
function balanceOfAt( function balanceOfAt(
address _owner, address _owner,
uint _blockNumber uint _blockNumber
) )
public public
constant view
returns (uint) returns (uint)
{ {
@ -335,10 +369,12 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
} }
} }
/// @notice Total amount of tokens at a specific `_blockNumber`. /**
/// @param _blockNumber The block number when the totalSupply is queried * @notice Total amount of tokens at a specific `_blockNumber`.
/// @return The total amount of tokens at `_blockNumber` * @param _blockNumber The block number when the totalSupply is queried
function totalSupplyAt(uint _blockNumber) public constant returns(uint) { * @return The total amount of tokens at `_blockNumber`
*/
function totalSupplyAt(uint _blockNumber) public view returns(uint) {
// These next few lines are used when the totalSupply of the token is // 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 // requested before a check point was ever created for this token, it
@ -363,16 +399,18 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// Clone Token Method // Clone Token Method
//////////////// ////////////////
/// @notice Creates a new clone token with the initial distribution being /**
/// this token at `_snapshotBlock` * @notice Creates a new clone token with the initial distribution being
/// @param _cloneTokenName Name of the clone token * this token at `snapshotBlock`
/// @param _cloneDecimalUnits Number of decimals of the smallest unit * @param _cloneTokenName Name of the clone token
/// @param _cloneTokenSymbol Symbol of the clone token * @param _cloneDecimalUnits Number of decimals of the smallest unit
/// @param _snapshotBlock Block when the distribution of the parent token is * @param _cloneTokenSymbol Symbol of the clone token
/// copied to set the initial distribution of the new clone token; * @param snapshotBlock Block when the distribution of the parent token is
/// if the block is zero than the actual block, the current block is used * copied to set the initial distribution of the new clone token;
/// @param _transfersEnabled True if transfers are allowed in the clone * if the block is zero than the actual block, the current block is used
/// @return The address of the new MiniMeToken Contract * @param _transfersEnabled True if transfers are allowed in the clone
* @return The address of the new MiniMeToken Contract
*/
function createCloneToken( function createCloneToken(
string _cloneTokenName, string _cloneTokenName,
uint8 _cloneDecimalUnits, uint8 _cloneDecimalUnits,
@ -383,12 +421,13 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
public public
returns(address) returns(address)
{ {
if (_snapshotBlock == 0) { uint snapshotBlock = _snapshotBlock;
_snapshotBlock = block.number; if (snapshotBlock == 0) {
snapshotBlock = block.number;
} }
MiniMeToken cloneToken = tokenFactory.createCloneToken( MiniMeToken cloneToken = tokenFactory.createCloneToken(
this, this,
_snapshotBlock, snapshotBlock,
_cloneTokenName, _cloneTokenName,
_cloneDecimalUnits, _cloneDecimalUnits,
_cloneTokenSymbol, _cloneTokenSymbol,
@ -398,7 +437,7 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
cloneToken.changeController(msg.sender); cloneToken.changeController(msg.sender);
// An event to make the token easy to find on the blockchain // An event to make the token easy to find on the blockchain
NewCloneToken(address(cloneToken), _snapshotBlock); emit NewCloneToken(address(cloneToken), snapshotBlock);
return address(cloneToken); return address(cloneToken);
} }
@ -406,10 +445,12 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// Generate and destroy tokens // Generate and destroy tokens
//////////////// ////////////////
/// @notice Generates `_amount` tokens that are assigned to `_owner` /**
/// @param _owner The address that will be assigned the new tokens * @notice Generates `_amount` tokens that are assigned to `_owner`
/// @param _amount The quantity of tokens generated * @param _owner The address that will be assigned the new tokens
/// @return True if the tokens are generated correctly * @param _amount The quantity of tokens generated
* @return True if the tokens are generated correctly
*/
function generateTokens( function generateTokens(
address _owner, address _owner,
uint _amount uint _amount
@ -418,21 +459,22 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
onlyController onlyController
returns (bool) returns (bool)
{ {
uint curTotalSupply = totalSupply(); uint curTotalSupply = totalSupplyAt(block.number);
require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow
uint previousBalanceTo = balanceOf(_owner); uint previousBalanceTo = balanceOfAt(_owner, block.number);
require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount); updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
updateValueAtNow(balances[_owner], previousBalanceTo + _amount); updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
Transfer(0, _owner, _amount); emit Transfer(0, _owner, _amount);
return true; return true;
} }
/**
/// @notice Burns `_amount` tokens from `_owner` * @notice Burns `_amount` tokens from `_owner`
/// @param _owner The address that will lose the tokens * @param _owner The address that will lose the tokens
/// @param _amount The quantity of tokens to burn * @param _amount The quantity of tokens to burn
/// @return True if the tokens are burned correctly * @return True if the tokens are burned correctly
*/
function destroyTokens( function destroyTokens(
address _owner, address _owner,
uint _amount uint _amount
@ -441,13 +483,13 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
onlyController onlyController
returns (bool) returns (bool)
{ {
uint curTotalSupply = totalSupply(); uint curTotalSupply = totalSupplyAt(block.number);
require(curTotalSupply >= _amount); require(curTotalSupply >= _amount);
uint previousBalanceFrom = balanceOf(_owner); uint previousBalanceFrom = balanceOfAt(_owner, block.number);
require(previousBalanceFrom >= _amount); require(previousBalanceFrom >= _amount);
updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount); updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
updateValueAtNow(balances[_owner], previousBalanceFrom - _amount); updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
Transfer(_owner, 0, _amount); emit Transfer(_owner, 0, _amount);
return true; return true;
} }
@ -455,9 +497,10 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// Enable tokens transfers // Enable tokens transfers
//////////////// ////////////////
/**
/// @notice Enables token holders to transfer their tokens freely if true * @notice Enables token holders to transfer their tokens freely if true
/// @param _transfersEnabled True if transfers are allowed in the clone * @param _transfersEnabled True if transfers are allowed in the clone
*/
function enableTransfers(bool _transfersEnabled) public onlyController { function enableTransfers(bool _transfersEnabled) public onlyController {
transfersEnabled = _transfersEnabled; transfersEnabled = _transfersEnabled;
} }
@ -466,10 +509,12 @@ contract MiniMeToken is MiniMeTokenInterface, 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 * @dev `getValueAt` retrieves the number of tokens at a given block number
/// @param _block The block number to retrieve the value at * @param checkpoints The history of values being queried
/// @return The number of tokens being queried * @param _block The block number to retrieve the value at
* @return The number of tokens being queried
*/
function getValueAt( function getValueAt(
Checkpoint[] storage checkpoints, Checkpoint[] storage checkpoints,
uint _block uint _block
@ -504,14 +549,16 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
return checkpoints[min].value; return checkpoints[min].value;
} }
/// @dev `updateValueAtNow` used to update the `balances` map and the /**
/// `totalSupplyHistory` * @dev `updateValueAtNow` used to update the `balances` map and the
/// @param checkpoints The history of data being updated * `totalSupplyHistory`
/// @param _value The new number of tokens * @param checkpoints The history of data being updated
* @param _value The new number of tokens
*/
function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value) internal { function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value) internal {
if ((checkpoints.length == 0) if ((checkpoints.length == 0)
|| (checkpoints[checkpoints.length -1].fromBlock < block.number)) { || (checkpoints[checkpoints.length -1].fromBlock < block.number)) {
Checkpoint storage newCheckPoint = checkpoints[ checkpoints.length++ ]; Checkpoint storage newCheckPoint = checkpoints[checkpoints.length++];
newCheckPoint.fromBlock = uint128(block.number); newCheckPoint.fromBlock = uint128(block.number);
newCheckPoint.value = uint128(_value); newCheckPoint.value = uint128(_value);
} else { } else {
@ -520,10 +567,12 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
} }
} }
/// @dev Internal function to determine if an address is a contract /**
/// @param _addr The address being queried * @dev Internal function to determine if an address is a contract
/// @return True if `_addr` is a contract * @param _addr The address being queried
function isContract(address _addr) constant internal returns(bool) { * @return True if `_addr` is a contract
*/
function isContract(address _addr) internal view returns(bool) {
uint size; uint size;
if (_addr == 0){ if (_addr == 0){
return false; return false;
@ -534,14 +583,18 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
return size>0; return size>0;
} }
/// @dev Helper function to return a min betwen the two uints /**
* @dev Helper function to return a min betwen the two uints
*/
function min(uint a, uint b) internal returns (uint) { function min(uint a, uint b) internal returns (uint) {
return a < b ? a : b; 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 * @notice The fallback function: If the contract's controller has not been
/// ether and creates tokens as described in the token controller contract * 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 { function () public payable {
require(isContract(controller)); require(isContract(controller));
require(TokenController(controller).proxyPayment.value(msg.value)(msg.sender)); require(TokenController(controller).proxyPayment.value(msg.value)(msg.sender));
@ -551,20 +604,22 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
// Safety Methods // Safety Methods
////////// //////////
/// @notice This method can be used by the controller to extract mistakenly /**
/// sent tokens to this contract. * @notice This method can be used by the controller to extract mistakenly
/// @param _token The address of the token contract that you want to recover * sent tokens to this contract.
/// set to 0 in case you want to extract ether. * @param _token The address of the token contract that you want to recover
* set to 0 in case you want to extract ether.
*/
function claimTokens(address _token) public onlyController { function claimTokens(address _token) public onlyController {
if (_token == 0x0) { if (_token == 0x0) {
controller.transfer(this.balance); controller.transfer(address(this).balance);
return; return;
} }
MiniMeToken token = MiniMeToken(_token); MiniMeToken token = MiniMeToken(_token);
uint balance = token.balanceOf(this); uint balance = token.balanceOf(address(this));
token.transfer(controller, balance); token.transfer(controller, balance);
ClaimedTokens(_token, controller, balance); emit ClaimedTokens(_token, controller, balance);
} }
//////////////// ////////////////
@ -572,7 +627,7 @@ contract MiniMeToken is MiniMeTokenInterface, Controlled {
//////////////// ////////////////
event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount); event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
event Transfer(address indexed _from, address indexed _to, uint256 _amount); event Transfer(address indexed _from, address indexed _to, uint256 _amount);
event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock); event NewCloneToken(address indexed _cloneToken, uint snapshotBlock);
event Approval( event Approval(
address indexed _owner, address indexed _owner,
address indexed _spender, address indexed _spender,

View File

@ -6,21 +6,25 @@ import "./MiniMeToken.sol";
// MiniMeTokenFactory // 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 * @dev This contract is used to generate clone contracts from a contract.
/// same class * In solidity this is the way to create a contract from a contract of the
* 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 * @notice Update the DApp by creating a new token with new functionalities
/// @param _parentToken Address of the token being cloned * the msg.sender becomes the controller of this clone token
/// @param _snapshotBlock Block of the parent token that will * @param _parentToken Address of the token being cloned
/// determine the initial distribution of the clone token * @param _snapshotBlock Block of the parent token that will
/// @param _tokenName Name of the new token * determine the initial distribution of the clone token
/// @param _decimalUnits Number of decimals of the new token * @param _tokenName Name of the new token
/// @param _tokenSymbol Token Symbol for the new token * @param _decimalUnits Number of decimals of the new token
/// @param _transfersEnabled If true, tokens will be able to be transferred * @param _tokenSymbol Token Symbol for the new token
/// @return The address of the new token contract * @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,

View File

@ -1,49 +1,19 @@
pragma solidity ^0.4.17; pragma solidity ^0.4.17;
contract MiniMeTokenInterface { import "./ERC20Token.sol";
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
/// @dev This function makes it easy to get the total number of tokens contract MiniMeTokenInterface is ERC20Token {
/// @return The total number of tokens
function totalSupply() public constant returns (uint);
/// @param _owner The address from which the balance will be retrieved /**
/// @return The balance * @notice `msg.sender` approves `_spender` to send `_amount` tokens on
function balanceOf(address _owner) public constant returns (uint256 balance); * its behalf, and then a function is triggered in the contract that is
* being approved, `_spender`. This allows users to use their tokens to
/// @notice send `_value` token to `_to` from `msg.sender` * interact with contracts in one function call instead of two
/// @param _to The address of the recipient * @param _spender The address of the contract able to transfer the tokens
/// @param _value The amount of token to be transferred * @param _amount The amount of tokens to be approved for transfer
/// @return Whether the transfer was successful or not * @return True if the function call was successful
function transfer(address _to, uint256 _value) public returns (bool success); */
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
/// @param _from The address of the sender
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
/// @return Whether the transfer was successful or not
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
/// @notice `msg.sender` approves `_spender` to spend `_value` tokens
/// @param _spender The address of the account able to transfer the tokens
/// @param _value The amount of tokens to be approved for transfer
/// @return Whether the approval was successful or not
function approve(address _spender, uint256 _value) public returns (bool success);
/// @param _owner The address of the account owning tokens
/// @param _spender The address of the account able to transfer the tokens
/// @return Amount of remaining tokens allowed to spent
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
/// @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( function approveAndCall(
address _spender, address _spender,
uint256 _amount, uint256 _amount,
@ -52,17 +22,18 @@ contract MiniMeTokenInterface {
public public
returns (bool success); returns (bool success);
/**
/// @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 Number of decimals of the smallest unit * @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;
/// if the block is zero than the actual block, the current block is used * if the block is zero than the actual block, the current block is used
/// @param _transfersEnabled True if transfers are allowed in the clone * @param _transfersEnabled True if transfers are allowed in the clone
/// @return The address of the new MiniMeToken Contract * @return The address of the new MiniMeToken Contract
*/
function createCloneToken( function createCloneToken(
string _cloneTokenName, string _cloneTokenName,
uint8 _cloneDecimalUnits, uint8 _cloneDecimalUnits,
@ -73,10 +44,12 @@ contract MiniMeTokenInterface {
public public
returns(address); returns(address);
/// @notice Generates `_amount` tokens that are assigned to `_owner` /**
/// @param _owner The address that will be assigned the new tokens * @notice Generates `_amount` tokens that are assigned to `_owner`
/// @param _amount The quantity of tokens generated * @param _owner The address that will be assigned the new tokens
/// @return True if the tokens are generated correctly * @param _amount The quantity of tokens generated
* @return True if the tokens are generated correctly
*/
function generateTokens( function generateTokens(
address _owner, address _owner,
uint _amount uint _amount
@ -84,10 +57,12 @@ contract MiniMeTokenInterface {
public public
returns (bool); returns (bool);
/// @notice Burns `_amount` tokens from `_owner` /**
/// @param _owner The address that will lose the tokens * @notice Burns `_amount` tokens from `_owner`
/// @param _amount The quantity of tokens to burn * @param _owner The address that will lose the tokens
/// @return True if the tokens are burned correctly * @param _amount The quantity of tokens to burn
* @return True if the tokens are burned correctly
*/
function destroyTokens( function destroyTokens(
address _owner, address _owner,
uint _amount uint _amount
@ -95,22 +70,26 @@ contract MiniMeTokenInterface {
public public
returns (bool); returns (bool);
/**
/// @notice Enables token holders to transfer their tokens freely if true * @notice Enables token holders to transfer their tokens freely if true
/// @param _transfersEnabled True if transfers are allowed in the clone * @param _transfersEnabled True if transfers are allowed in the clone
*/
function enableTransfers(bool _transfersEnabled) public; function enableTransfers(bool _transfersEnabled) public;
/**
/// @notice This method can be used by the controller to extract mistakenly * @notice This method can be used by the controller to extract mistakenly
/// sent tokens to this contract. * sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover * @param _token The address of the token contract that you want to recover
/// set to 0 in case you want to extract ether. * set to 0 in case you want to extract ether.
*/
function claimTokens(address _token) public; function claimTokens(address _token) public;
/// @dev Queries the balance of `_owner` at a specific `_blockNumber` /**
/// @param _owner The address from which the balance will be retrieved * @dev Queries the balance of `_owner` at a specific `_blockNumber`
/// @param _blockNumber The block number when the balance is queried * @param _owner The address from which the balance will be retrieved
/// @return The balance at `_blockNumber` * @param _blockNumber The block number when the balance is queried
* @return The balance at `_blockNumber`
*/
function balanceOfAt( function balanceOfAt(
address _owner, address _owner,
uint _blockNumber uint _blockNumber
@ -119,11 +98,11 @@ contract MiniMeTokenInterface {
constant constant
returns (uint); returns (uint);
/// @notice Total amount of tokens at a specific `_blockNumber`. /**
/// @param _blockNumber The block number when the totalSupply is queried * @notice Total amount of tokens at a specific `_blockNumber`.
/// @return The total amount of tokens at `_blockNumber` * @param _blockNumber The block number when the totalSupply is queried
function totalSupplyAt(uint _blockNumber) public constant returns(uint); * @return The total amount of tokens at `_blockNumber`
*/
function totalSupplyAt(uint _blockNumber) public view returns(uint);
} }

View File

@ -4,6 +4,7 @@ import "./ERC20Token.sol";
contract StandardToken is ERC20Token { contract StandardToken is ERC20Token {
uint256 private supply;
mapping (address => uint256) balances; mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed; mapping (address => mapping (address => uint256)) allowed;
@ -13,14 +14,14 @@ contract StandardToken is ERC20Token {
address _to, address _to,
uint256 _value uint256 _value
) )
public external
returns (bool success) returns (bool success)
{ {
return transfer(msg.sender, _to, _value); return transfer(msg.sender, _to, _value);
} }
function approve(address _spender, uint256 _value) function approve(address _spender, uint256 _value)
public external
returns (bool success) returns (bool success)
{ {
allowed[msg.sender][_spender] = _value; allowed[msg.sender][_spender] = _value;
@ -33,7 +34,7 @@ contract StandardToken is ERC20Token {
address _to, address _to,
uint256 _value uint256 _value
) )
public external
returns (bool success) returns (bool success)
{ {
if (balances[_from] >= _value && if (balances[_from] >= _value &&
@ -47,7 +48,7 @@ contract StandardToken is ERC20Token {
} }
function allowance(address _owner, address _spender) function allowance(address _owner, address _spender)
public external
view view
returns (uint256 remaining) returns (uint256 remaining)
{ {
@ -55,13 +56,32 @@ contract StandardToken is ERC20Token {
} }
function balanceOf(address _owner) function balanceOf(address _owner)
public external
view view
returns (uint256 balance) returns (uint256 balance)
{ {
return balances[_owner]; return balances[_owner];
} }
function totalSupply()
external
view
returns(uint256 supply)
{
return supply;
}
function mint(
address _to,
uint256 _amount
)
internal
{
balances[_to] += _amount;
supply += _amount;
emit Transfer(0x0, _to, _amount);
}
function transfer( function transfer(
address _from, address _from,
address _to, address _to,

View File

@ -0,0 +1,19 @@
pragma solidity ^0.4.23;
import "./StandardToken.sol";
/**
* @notice ERC20Token for test scripts, can be minted by anyone.
*/
contract TestToken is StandardToken {
constructor() public { }
/**
* @notice any caller can mint any `_amount`
* @param _amount how much to be minted
*/
function mint(uint256 _amount) public {
mint(msg.sender, _amount);
}
}

View File

@ -1,26 +1,33 @@
pragma solidity ^0.4.14; pragma solidity ^0.4.14;
/**
/// @dev The token controller contract must implement these functions * @dev The token controller contract must implement these functions
*/
contract TokenController { contract TokenController {
/// @notice Called when `_owner` sends ether to the MiniMe Token contract /**
/// @param _owner The address that sent the ether to create tokens * @notice Called when `_owner` sends ether to the MiniMe Token contract
/// @return True if the ether is accepted, false if it throws * @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); function proxyPayment(address _owner) payable returns(bool);
/// @notice Notifies the controller about a token transfer allowing the /**
/// controller to react if desired * @notice Notifies the controller about a token transfer allowing the
/// @param _from The origin of the transfer * controller to react if desired
/// @param _to The destination of the transfer * @param _from The origin of the transfer
/// @param _amount The amount of the transfer * @param _to The destination of the transfer
/// @return False if the controller does not authorize 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); function onTransfer(address _from, address _to, uint _amount) returns(bool);
/// @notice Notifies the controller about an approval allowing the /**
/// controller to react if desired * @notice Notifies the controller about an approval allowing the
/// @param _owner The address that calls `approve()` * controller to react if desired
/// @param _spender The spender in the `approve()` call * @param _owner The address that calls `approve()`
/// @param _amount The amount in the `approve()` call * @param _spender The spender in the `approve()` call
/// @return False if the controller does not authorize the approval * @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) function onApprove(address _owner, address _spender, uint _amount)
returns(bool); returns(bool);
} }