2016-11-08 13:18:27 +00:00
/*
Author : Jordi Baylina
License : GPL 3 . 0
* /
2016-11-08 13:12:24 +00:00
pragma solidity ^ 0 . 4 . 4 ;
contract Owned {
/// Allows only the owner to call a function
modifier onlyOwner { if ( msg . sender != owner ) throw ; _ ; }
address public owner ;
function Owned ( ) { owner = msg . sender ; }
function changeOwner ( address _newOwner ) onlyOwner {
owner = _newOwner ;
}
}
contract MiniMeToken is Owned {
string public name ; //fancy name: eg Simon Bucks
uint8 public decimals ; //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.
string public symbol ; //An identifier: eg SBX
string public version = ' H0.1 ' ; //human 0.1 standard. Just an arbitrary versioning scheme.
struct Checkpoint {
// snapshot when starts to take effect this assignation
uint fromBlock ;
// balance assigned to token holder from this snapshot
uint value ;
}
MiniMeToken public parentToken ;
uint public parentSnapShotBlock ;
uint public creationBlock ;
mapping ( address => Checkpoint [ ] ) balances ;
mapping ( address => mapping ( address => uint256 ) ) allowed ;
Checkpoint [ ] totalSupplyHistory ;
bool public isConstant ;
MiniMeTokenFactory public tokenFactory ;
////////////////
// Constructor
////////////////
function MiniMeToken (
address _tokenFactory ,
address _parentToken ,
uint _parentSnapShotBlock ,
string _tokenName ,
uint8 _decimalUnits ,
string _tokenSymbol ,
bool _isConstant
) {
tokenFactory = MiniMeTokenFactory ( _tokenFactory ) ;
name = _tokenName ; // Set the name for display purposes
decimals = _decimalUnits ; // Amount of decimals for display purposes
symbol = _tokenSymbol ; // Set the symbol for display purposes
parentToken = MiniMeToken ( _parentToken ) ;
parentSnapShotBlock = _parentSnapShotBlock ;
isConstant = _isConstant ;
creationBlock = block . number ;
}
////////////////
// ERC20 Interface
////////////////
function transfer ( address _to , uint256 _value ) returns ( bool success ) {
return doTransfer ( msg . sender , _to , _value ) ;
}
function transferFrom ( address _from , address _to , uint256 _value ) returns ( bool success ) {
//same as above. Replace this line with the following if you want to protect against wrapping uints.
//if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
if ( isConstant ) throw ;
if ( msg . sender != owner ) {
if ( allowed [ _from ] [ msg . sender ] < _value ) return false ;
allowed [ _from ] [ msg . sender ] -= _value ;
}
return doTransfer ( _from , _to , _value ) ;
}
function doTransfer ( address _from , address _to , uint _value ) internal returns ( bool ) {
if ( _value == 0 ) {
return true ;
}
// Do not allow transfer to this
if ( ( _to == 0 ) || ( _to == address ( this ) ) ) throw ;
// Remove _from votes
var previousBalanceFrom = balanceOfAt ( _from , block . number ) ;
if ( previousBalanceFrom < _value ) {
return false ;
}
updateValueAtNow ( balances [ _from ] , previousBalanceFrom - _value ) ;
var previousBalanceTo = balanceOfAt ( _to , block . number ) ;
updateValueAtNow ( balances [ _to ] , previousBalanceTo + _value ) ;
Transfer ( _from , _to , _value ) ;
return true ;
}
function balanceOf ( address _owner ) constant returns ( uint256 balance ) {
return balanceOfAt ( _owner , block . number ) ;
}
function approve ( address _spender , uint256 _value ) returns ( bool success ) {
if ( isConstant ) throw ;
allowed [ msg . sender ] [ _spender ] = _value ;
Approval ( msg . sender , _spender , _value ) ;
return true ;
}
function allowance ( address _owner , address _spender ) constant returns ( uint256 remaining ) {
return allowed [ _owner ] [ _spender ] ;
}
/* Approves and then calls the receiving contract */
function approveAndCall ( address _spender , uint256 _value , bytes _extraData ) returns ( bool success ) {
if ( isConstant ) throw ;
allowed [ msg . sender ] [ _spender ] = _value ;
Approval ( msg . sender , _spender , _value ) ;
//call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
//receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
//it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.
if ( ! _spender . call ( bytes4 ( bytes32 ( sha3 ( " receiveApproval(address,uint256,address,bytes) " ) ) ) , msg . sender , _value , this , _extraData ) ) { throw ; }
return true ;
}
function totalSupply ( ) constant returns ( uint ) {
return totalSupplyAt ( block . number ) ;
}
////////////////
// Query balance and totalSupply in History
////////////////
function balanceOfAt ( address _holder , uint _blockNumber ) constant returns ( uint ) {
if ( _blockNumber < creationBlock ) {
return 0 ;
} else if ( ( balances [ _holder ] . length == 0 ) || ( balances [ _holder ] [ 0 ] . fromBlock > _blockNumber ) ) {
if ( address ( parentToken ) != 0 ) {
return parentToken . balanceOfAt ( _holder , parentSnapShotBlock ) ;
} else {
return 0 ;
}
} else {
return getValueAt ( balances [ _holder ] , _blockNumber ) ;
}
}
function totalSupplyAt ( uint _blockNumber ) constant returns ( uint ) {
if ( _blockNumber < creationBlock ) {
return 0 ;
} else if ( ( totalSupplyHistory . length == 0 ) || ( totalSupplyHistory [ 0 ] . fromBlock > _blockNumber ) ) {
if ( address ( parentToken ) != 0 ) {
return parentToken . totalSupplyAt ( parentSnapShotBlock ) ;
} else {
return 0 ;
}
} else {
return getValueAt ( totalSupplyHistory , _blockNumber ) ;
}
}
////////////////
// Create a child token from an snapshot of this token at a given block
////////////////
function createChildToken ( string _childTokenName , uint8 _childDecimalUnits , string _childTokenSymbol , uint _snapshotBlock , bool _isConstant ) returns ( address ) {
if ( _snapshotBlock > block . number ) _snapshotBlock = block . number ;
MiniMeToken childToken = tokenFactory . createChildToken ( this , _snapshotBlock , _childTokenName , _childDecimalUnits , _childTokenSymbol , _isConstant ) ;
NewChildToken ( address ( childToken ) , _snapshotBlock ) ;
return address ( childToken ) ;
}
////////////////
// Generate and destroy tokens
////////////////
function generateTokens ( address _holder , uint _value ) onlyOwner {
if ( isConstant ) throw ;
uint curTotalSupply = getValueAt ( totalSupplyHistory , block . number ) ;
updateValueAtNow ( totalSupplyHistory , curTotalSupply + _value ) ;
var previousBalanceTo = balanceOf ( _holder ) ;
updateValueAtNow ( balances [ _holder ] , previousBalanceTo + _value ) ;
Transfer ( 0 , _holder , _value ) ;
}
function destroyTokens ( address _holder , uint _value ) onlyOwner {
if ( isConstant ) throw ;
uint curTotalSupply = getValueAt ( totalSupplyHistory , block . number ) ;
if ( curTotalSupply < _value ) throw ;
updateValueAtNow ( totalSupplyHistory , curTotalSupply - _value ) ;
var previousBalanceFrom = balanceOf ( _holder ) ;
if ( previousBalanceFrom < _value ) throw ;
updateValueAtNow ( balances [ _holder ] , previousBalanceFrom - _value ) ;
Transfer ( _holder , 0 , _value ) ;
}
////////////////
// Constant tokens
////////////////
function setConstant ( bool _isConstant ) onlyOwner {
isConstant = _isConstant ;
}
////////////////
// Internal helper functions to query and set a value in a snapshot array
////////////////
function getValueAt ( Checkpoint [ ] storage checkpoints , uint _block ) constant internal returns ( uint ) {
if ( checkpoints . length == 0 ) return 0 ;
//Shorcut for the actual value
if ( _block >= checkpoints [ checkpoints . length - 1 ] . fromBlock ) return checkpoints [ checkpoints . length - 1 ] . value ;
if ( _block < checkpoints [ 0 ] . fromBlock ) return 0 ;
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 ;
}
function updateValueAtNow ( Checkpoint [ ] storage checkpoints , uint _value ) internal {
if ( ( checkpoints . length == 0 ) || ( checkpoints [ checkpoints . length - 1 ] . fromBlock < block . number ) ) {
Checkpoint newCheckPoint = checkpoints [ checkpoints . length ++ ] ;
newCheckPoint . fromBlock = block . number ;
newCheckPoint . value = _value ;
} else {
Checkpoint oldCheckPoint = checkpoints [ checkpoints . length - 1 ] ;
oldCheckPoint . value = _value ;
}
}
event Transfer ( address indexed _from , address indexed _to , uint256 _value ) ;
event Approval ( address indexed _owner , address indexed _spender , uint256 _value ) ;
event NewChildToken ( address indexed _childToken , uint _snapshotBlock ) ;
}
contract MiniMeTokenFactory {
function createChildToken (
address _parentToken ,
uint _snapshotBlock ,
string _tokenName ,
uint8 _decimalUnits ,
string _tokenSymbol ,
bool _isConstant
) returns ( MiniMeToken ) {
MiniMeToken newToken = new MiniMeToken ( this , _parentToken , _snapshotBlock , _tokenName , _decimalUnits , _tokenSymbol , _isConstant ) ;
return newToken ;
}
}