Merge with master
This commit is contained in:
@ -2,7 +2,7 @@ pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import './payment/PullPayment.sol';
|
||||
import './lifecycle/Killable.sol';
|
||||
import './lifecycle/Destructible.sol';
|
||||
|
||||
|
||||
/*
|
||||
@ -10,7 +10,7 @@ import './lifecycle/Killable.sol';
|
||||
*
|
||||
* This bounty will pay out to a researcher if they break invariant logic of the contract.
|
||||
*/
|
||||
contract Bounty is PullPayment, Killable {
|
||||
contract Bounty is PullPayment, Destructible {
|
||||
bool public claimed;
|
||||
mapping(address => address) public researchers;
|
||||
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import './ownership/Shareable.sol';
|
||||
|
||||
|
||||
/*
|
||||
* DayLimit
|
||||
*
|
||||
|
||||
@ -24,9 +24,9 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
|
||||
Shareable(_owners, _required)
|
||||
DayLimit(_daylimit) { }
|
||||
|
||||
// kills the contract sending everything to `_to`.
|
||||
function kill(address _to) onlymanyowners(sha3(msg.data)) external {
|
||||
suicide(_to);
|
||||
// destroys the contract sending everything to `_to`.
|
||||
function destroy(address _to) onlymanyowners(keccak256(msg.data)) external {
|
||||
selfdestruct(_to);
|
||||
}
|
||||
|
||||
// gets called when no other function matches
|
||||
@ -51,7 +51,7 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
|
||||
return 0;
|
||||
}
|
||||
// determine our operation hash.
|
||||
_r = sha3(msg.data, block.number);
|
||||
_r = keccak256(msg.data, block.number);
|
||||
if (!confirm(_r) && txs[_r].to == 0) {
|
||||
txs[_r].to = _to;
|
||||
txs[_r].value = _value;
|
||||
@ -73,11 +73,11 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
|
||||
}
|
||||
}
|
||||
|
||||
function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external {
|
||||
function setDailyLimit(uint _newLimit) onlymanyowners(keccak256(msg.data)) external {
|
||||
_setDailyLimit(_newLimit);
|
||||
}
|
||||
|
||||
function resetSpentToday() onlymanyowners(sha3(msg.data)) external {
|
||||
function resetSpentToday() onlymanyowners(keccak256(msg.data)) external {
|
||||
_resetSpentToday();
|
||||
}
|
||||
|
||||
|
||||
28
contracts/ReentrancyGuard.sol
Normal file
28
contracts/ReentrancyGuard.sol
Normal file
@ -0,0 +1,28 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
/// @title Helps contracts guard agains rentrancy attacks.
|
||||
/// @author Remco Bloemen <remco@2π.com>
|
||||
/// @notice If you mark a function `nonReentrant`, you should also
|
||||
/// mark it `external`.
|
||||
contract ReentrancyGuard {
|
||||
|
||||
/// @dev We use a single lock for the whole contract.
|
||||
bool private rentrancy_lock = false;
|
||||
|
||||
/// Prevent contract from calling itself, directly or indirectly.
|
||||
/// @notice If you mark a function `nonReentrant`, you should also
|
||||
/// mark it `external`. Calling one nonReentrant function from
|
||||
/// another is not supported. Instead, you can implement a
|
||||
/// `private` function doing the actual work, and a `external`
|
||||
/// wrapper marked as `nonReentrant`.
|
||||
modifier nonReentrant() {
|
||||
if(rentrancy_lock == false) {
|
||||
rentrancy_lock = true;
|
||||
_;
|
||||
rentrancy_lock = false;
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,28 +4,28 @@ pragma solidity ^0.4.8;
|
||||
/**
|
||||
* Math operations with safety checks
|
||||
*/
|
||||
contract SafeMath {
|
||||
function safeMul(uint a, uint b) internal returns (uint) {
|
||||
library SafeMath {
|
||||
function mul(uint a, uint b) internal returns (uint) {
|
||||
uint c = a * b;
|
||||
assert(a == 0 || c / a == b);
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeDiv(uint a, uint b) internal returns (uint) {
|
||||
function div(uint a, uint b) internal returns (uint) {
|
||||
assert(b > 0);
|
||||
uint c = a / b;
|
||||
assert(a == b * c + a % b);
|
||||
return c;
|
||||
}
|
||||
|
||||
function safeSub(uint a, uint b) internal returns (uint) {
|
||||
function sub(uint a, uint b) internal returns (uint) {
|
||||
assert(b <= a);
|
||||
return a - b;
|
||||
}
|
||||
|
||||
function safeAdd(uint a, uint b) internal returns (uint) {
|
||||
function add(uint a, uint b) internal returns (uint) {
|
||||
uint c = a + b;
|
||||
assert(c>=a && c>=b);
|
||||
assert(c >= a);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
19
contracts/lifecycle/Destructible.sol
Normal file
19
contracts/lifecycle/Destructible.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/*
|
||||
* Destructible
|
||||
* Base contract that can be destroyed by owner. All funds in contract will be sent to the owner.
|
||||
*/
|
||||
contract Destructible is Ownable {
|
||||
function destroy() onlyOwner {
|
||||
selfdestruct(owner);
|
||||
}
|
||||
|
||||
function destroyAndSend(address _recipient) onlyOwner {
|
||||
selfdestruct(_recipient);
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/*
|
||||
* Killable
|
||||
* Base contract that can be killed by owner. All funds in contract will be sent to the owner.
|
||||
*/
|
||||
contract Killable is Ownable {
|
||||
function kill() onlyOwner {
|
||||
selfdestruct(owner);
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ pragma solidity ^0.4.8;
|
||||
import '../ownership/Ownable.sol';
|
||||
|
||||
|
||||
// This is a truffle contract, needed for truffle integration, not meant for use by Zeppelin users.
|
||||
contract Migrations is Ownable {
|
||||
uint public lastCompletedMigration;
|
||||
|
||||
|
||||
@ -6,32 +6,36 @@ import "../ownership/Ownable.sol";
|
||||
|
||||
/*
|
||||
* Pausable
|
||||
* Abstract contract that allows children to implement an
|
||||
* emergency stop mechanism.
|
||||
* Abstract contract that allows children to implement a
|
||||
* pause mechanism.
|
||||
*/
|
||||
contract Pausable is Ownable {
|
||||
bool public stopped;
|
||||
event Pause();
|
||||
event Unpause();
|
||||
|
||||
modifier stopInEmergency {
|
||||
if (!stopped) {
|
||||
_;
|
||||
}
|
||||
}
|
||||
|
||||
modifier onlyInEmergency {
|
||||
if (stopped) {
|
||||
_;
|
||||
}
|
||||
bool public paused = false;
|
||||
|
||||
modifier whenNotPaused() {
|
||||
if (paused) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
// called by the owner on emergency, triggers stopped state
|
||||
function emergencyStop() external onlyOwner {
|
||||
stopped = true;
|
||||
modifier whenPaused {
|
||||
if (!paused) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
// called by the owner on end of emergency, returns to normal state
|
||||
function release() external onlyOwner onlyInEmergency {
|
||||
stopped = false;
|
||||
// called by the owner to pause, triggers stopped state
|
||||
function pause() onlyOwner whenNotPaused returns (bool) {
|
||||
paused = true;
|
||||
Pause();
|
||||
return true;
|
||||
}
|
||||
|
||||
// called by the owner to unpause, returns to normal state
|
||||
function unpause() onlyOwner whenPaused returns (bool) {
|
||||
paused = false;
|
||||
Unpause();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
30
contracts/lifecycle/TokenDestructible.sol
Normal file
30
contracts/lifecycle/TokenDestructible.sol
Normal file
@ -0,0 +1,30 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../token/ERC20Basic.sol";
|
||||
|
||||
/// @title TokenDestructible:
|
||||
/// @author Remco Bloemen <remco@2π.com>
|
||||
///.Base contract that can be destroyed by owner. All funds in contract including
|
||||
/// listed tokens will be sent to the owner
|
||||
contract TokenDestructible is Ownable {
|
||||
|
||||
/// @notice Terminate contract and refund to owner
|
||||
/// @param tokens List of addresses of ERC20 or ERC20Basic token contracts to
|
||||
// refund
|
||||
/// @notice The called token contracts could try to re-enter this contract.
|
||||
// Only supply token contracts you
|
||||
function destroy(address[] tokens) onlyOwner {
|
||||
|
||||
// Transfer tokens to owner
|
||||
for(uint i = 0; i < tokens.length; i++) {
|
||||
ERC20Basic token = ERC20Basic(tokens[i]);
|
||||
uint256 balance = token.balanceOf(this);
|
||||
token.transfer(owner, balance);
|
||||
}
|
||||
|
||||
// Transfer Eth to owner and terminate contract
|
||||
selfdestruct(owner);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.0;
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import './Ownable.sol';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.0;
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import './Ownable.sol';
|
||||
/*
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import './Ownable.sol';
|
||||
import './Claimable.sol';
|
||||
|
||||
|
||||
@ -9,7 +8,7 @@ import './Claimable.sol';
|
||||
* DelayedClaimable
|
||||
* Extension for the Claimable contract, where the ownership needs to be claimed before/after certain block number
|
||||
*/
|
||||
contract DelayedClaimable is Ownable, Claimable {
|
||||
contract DelayedClaimable is Claimable {
|
||||
|
||||
uint public end;
|
||||
uint public start;
|
||||
|
||||
18
contracts/ownership/HasNoContracts.sol
Normal file
18
contracts/ownership/HasNoContracts.sol
Normal file
@ -0,0 +1,18 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
/// @title Contracts that should not own Contracts
|
||||
/// @author Remco Bloemen <remco@2π.com>
|
||||
///
|
||||
/// Should contracts (anything Ownable) end up being owned by
|
||||
/// this contract, it allows the owner of this contract to
|
||||
/// reclaim ownership of the contracts.
|
||||
contract HasNoContracts is Ownable {
|
||||
|
||||
/// Reclaim ownership of Ownable contracts
|
||||
function reclaimContract(address contractAddr) external onlyOwner {
|
||||
Ownable contractInst = Ownable(contractAddr);
|
||||
contractInst.transferOwnership(owner);
|
||||
}
|
||||
}
|
||||
42
contracts/ownership/HasNoEther.sol
Normal file
42
contracts/ownership/HasNoEther.sol
Normal file
@ -0,0 +1,42 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
/// @title Contracts that should not own Ether
|
||||
/// @author Remco Bloemen <remco@2π.com>
|
||||
///
|
||||
/// This tries to block incoming ether to prevent accidental
|
||||
/// loss of Ether. Should Ether end up in the contrat, it will
|
||||
/// allow the owner to reclaim this ether.
|
||||
///
|
||||
/// @notice Ether can still be send to this contract by:
|
||||
/// * calling functions labeled `payable`
|
||||
/// * `selfdestruct(contract_address)`
|
||||
/// * mining directly to the contract address
|
||||
contract HasNoEther is Ownable {
|
||||
|
||||
/// Constructor that rejects incoming Ether
|
||||
/// @dev The flag `payable` is added so we can access `msg.value`
|
||||
/// without compiler warning. If we leave out payable, then
|
||||
/// Solidity will allow inheriting contracts to implement a
|
||||
/// payable constructor. By doing it this way we prevent a
|
||||
/// payable constructor from working.
|
||||
/// Alternatively we could use assembly to access msg.value.
|
||||
function HasNoEther() payable {
|
||||
if(msg.value > 0) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// Disallow direct send by settings a default function without `payable`
|
||||
function() external {
|
||||
}
|
||||
|
||||
/// Transfer all Ether owned by the contract to the owner
|
||||
/// @dev What if owner is itself a contract marked HasNoEther?
|
||||
function reclaimEther() external onlyOwner {
|
||||
if(!owner.send(this.balance)) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
contracts/ownership/HasNoTokens.sol
Normal file
26
contracts/ownership/HasNoTokens.sol
Normal file
@ -0,0 +1,26 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import "./Ownable.sol";
|
||||
import "../token/ERC20Basic.sol";
|
||||
|
||||
/// @title Contracts that should not own Tokens
|
||||
/// @author Remco Bloemen <remco@2π.com>
|
||||
///
|
||||
/// This blocks incoming ERC23 tokens to prevent accidental
|
||||
/// loss of tokens. Should tokens (any ERC20Basic compatible)
|
||||
/// end up in the contract, it allows the owner to reclaim
|
||||
/// the tokens.
|
||||
contract HasNoTokens is Ownable {
|
||||
|
||||
/// Reject all ERC23 compatible tokens
|
||||
function tokenFallback(address from_, uint value_, bytes data_) external {
|
||||
throw;
|
||||
}
|
||||
|
||||
/// Reclaim all ERC20Basic compatible tokens
|
||||
function reclaimToken(address tokenAddr) external onlyOwner {
|
||||
ERC20Basic tokenInst = ERC20Basic(tokenAddr);
|
||||
uint256 balance = tokenInst.balanceOf(this);
|
||||
tokenInst.transfer(owner, balance);
|
||||
}
|
||||
}
|
||||
14
contracts/ownership/NoOwner.sol
Normal file
14
contracts/ownership/NoOwner.sol
Normal file
@ -0,0 +1,14 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import "./HasNoEther.sol";
|
||||
import "./HasNoTokens.sol";
|
||||
import "./HasNoContracts.sol";
|
||||
|
||||
/// @title Base contract for contracts that should not own things.
|
||||
/// @author Remco Bloemen <remco@2π.com>
|
||||
///
|
||||
/// Solves a class of errors where a contract accidentally
|
||||
/// becomes owner of Ether, Tokens or Owned contracts. See
|
||||
/// respective base contracts for details.
|
||||
contract NoOwner is HasNoEther, HasNoTokens, HasNoContracts {
|
||||
}
|
||||
@ -23,9 +23,9 @@ contract Shareable {
|
||||
uint public required;
|
||||
|
||||
// list of owners
|
||||
uint[256] owners;
|
||||
address[256] owners;
|
||||
// index on the list of owners to allow reverse lookup
|
||||
mapping(uint => uint) ownerIndex;
|
||||
mapping(address => uint) ownerIndex;
|
||||
// the ongoing operations.
|
||||
mapping(bytes32 => PendingState) pendings;
|
||||
bytes32[] pendingsIndex;
|
||||
@ -57,18 +57,21 @@ contract Shareable {
|
||||
// constructor is given number of sigs required to do protected "onlymanyowners" transactions
|
||||
// as well as the selection of addresses capable of confirming them.
|
||||
function Shareable(address[] _owners, uint _required) {
|
||||
owners[1] = uint(msg.sender);
|
||||
ownerIndex[uint(msg.sender)] = 1;
|
||||
owners[1] = msg.sender;
|
||||
ownerIndex[msg.sender] = 1;
|
||||
for (uint i = 0; i < _owners.length; ++i) {
|
||||
owners[2 + i] = uint(_owners[i]);
|
||||
ownerIndex[uint(_owners[i])] = 2 + i;
|
||||
owners[2 + i] = _owners[i];
|
||||
ownerIndex[_owners[i]] = 2 + i;
|
||||
}
|
||||
required = _required;
|
||||
if (required > owners.length) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Revokes a prior confirmation of the given operation
|
||||
function revoke(bytes32 _operation) external {
|
||||
uint index = ownerIndex[uint(msg.sender)];
|
||||
uint index = ownerIndex[msg.sender];
|
||||
// make sure they're an owner
|
||||
if (index == 0) {
|
||||
return;
|
||||
@ -88,12 +91,12 @@ contract Shareable {
|
||||
}
|
||||
|
||||
function isOwner(address _addr) constant returns (bool) {
|
||||
return ownerIndex[uint(_addr)] > 0;
|
||||
return ownerIndex[_addr] > 0;
|
||||
}
|
||||
|
||||
function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) {
|
||||
var pending = pendings[_operation];
|
||||
uint index = ownerIndex[uint(_owner)];
|
||||
uint index = ownerIndex[_owner];
|
||||
|
||||
// make sure they're an owner
|
||||
if (index == 0) {
|
||||
@ -105,12 +108,13 @@ contract Shareable {
|
||||
return !(pending.ownersDone & ownerIndexBit == 0);
|
||||
}
|
||||
|
||||
// returns true when operation can be executed
|
||||
function confirmAndCheck(bytes32 _operation) internal returns (bool) {
|
||||
// determine what index the present sender is:
|
||||
uint index = ownerIndex[uint(msg.sender)];
|
||||
uint index = ownerIndex[msg.sender];
|
||||
// make sure they're an owner
|
||||
if (index == 0) {
|
||||
return;
|
||||
throw;
|
||||
}
|
||||
|
||||
var pending = pendings[_operation];
|
||||
@ -140,6 +144,7 @@ contract Shareable {
|
||||
pending.ownersDone |= ownerIndexBit;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function clearPending() internal {
|
||||
|
||||
@ -1,24 +1,31 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import '../SafeMath.sol';
|
||||
|
||||
|
||||
/*
|
||||
* PullPayment
|
||||
* Base contract supporting async send for pull payments.
|
||||
* Inherit from this contract and use asyncSend instead of send.
|
||||
*/
|
||||
contract PullPayment {
|
||||
using SafeMath for uint;
|
||||
|
||||
mapping(address => uint) public payments;
|
||||
uint public totalPayments;
|
||||
|
||||
// store sent amount as credit to be pulled, called by payer
|
||||
function asyncSend(address dest, uint amount) internal {
|
||||
payments[dest] += amount;
|
||||
payments[dest] = payments[dest].add(amount);
|
||||
totalPayments = totalPayments.add(amount);
|
||||
}
|
||||
|
||||
// withdraw accumulated balance, called by payee
|
||||
function withdrawPayments() {
|
||||
address payee = msg.sender;
|
||||
uint payment = payments[payee];
|
||||
|
||||
|
||||
if (payment == 0) {
|
||||
throw;
|
||||
}
|
||||
@ -27,6 +34,7 @@ contract PullPayment {
|
||||
throw;
|
||||
}
|
||||
|
||||
totalPayments = totalPayments.sub(payment);
|
||||
payments[payee] = 0;
|
||||
|
||||
if (!payee.send(payment)) {
|
||||
|
||||
@ -9,13 +9,24 @@ import '../SafeMath.sol';
|
||||
* Basic token
|
||||
* Basic version of StandardToken, with no allowances
|
||||
*/
|
||||
contract BasicToken is ERC20Basic, SafeMath {
|
||||
contract BasicToken is ERC20Basic {
|
||||
using SafeMath for uint;
|
||||
|
||||
mapping(address => uint) balances;
|
||||
|
||||
function transfer(address _to, uint _value) {
|
||||
balances[msg.sender] = safeSub(balances[msg.sender], _value);
|
||||
balances[_to] = safeAdd(balances[_to], _value);
|
||||
/*
|
||||
* Fix for the ERC20 short address attack
|
||||
*/
|
||||
modifier onlyPayloadSize(uint size) {
|
||||
if(msg.data.length < size + 4) {
|
||||
throw;
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) {
|
||||
balances[msg.sender] = balances[msg.sender].sub(_value);
|
||||
balances[_to] = balances[_to].add(_value);
|
||||
Transfer(msg.sender, _to, _value);
|
||||
}
|
||||
|
||||
|
||||
@ -8,15 +8,20 @@ import "./StandardToken.sol";
|
||||
* CrowdsaleToken
|
||||
*
|
||||
* Simple ERC20 Token example, with crowdsale token creation
|
||||
* IMPORTANT NOTE: do not use or deploy this contract as-is.
|
||||
* It needs some changes to be production ready.
|
||||
*/
|
||||
contract CrowdsaleToken is StandardToken {
|
||||
|
||||
string public name = "CrowdsaleToken";
|
||||
string public symbol = "CRW";
|
||||
uint public decimals = 18;
|
||||
string public constant name = "CrowdsaleToken";
|
||||
string public constant symbol = "CRW";
|
||||
uint public constant decimals = 18;
|
||||
// replace with your fund collection multisig address
|
||||
address public constant multisig = 0x0;
|
||||
|
||||
|
||||
// 1 ether = 500 example tokens
|
||||
uint PRICE = 500;
|
||||
uint public constant PRICE = 500;
|
||||
|
||||
function () payable {
|
||||
createTokens(msg.sender);
|
||||
@ -27,10 +32,14 @@ contract CrowdsaleToken is StandardToken {
|
||||
throw;
|
||||
}
|
||||
|
||||
uint tokens = safeMul(msg.value, getPrice());
|
||||
uint tokens = msg.value.mul(getPrice());
|
||||
totalSupply = totalSupply.add(tokens);
|
||||
|
||||
totalSupply = safeAdd(totalSupply, tokens);
|
||||
balances[recipient] = safeAdd(balances[recipient], tokens);
|
||||
balances[recipient] = balances[recipient].add(tokens);
|
||||
|
||||
if (!multisig.send(msg.value)) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// replace this with any other price function
|
||||
|
||||
@ -1,18 +1,16 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import './ERC20Basic.sol';
|
||||
|
||||
|
||||
/*
|
||||
* ERC20 interface
|
||||
* see https://github.com/ethereum/EIPs/issues/20
|
||||
*/
|
||||
contract ERC20 {
|
||||
uint public totalSupply;
|
||||
function balanceOf(address who) constant returns (uint);
|
||||
contract ERC20 is ERC20Basic {
|
||||
function allowance(address owner, address spender) constant returns (uint);
|
||||
|
||||
function transfer(address to, uint value) returns (bool ok);
|
||||
function transferFrom(address from, address to, uint value) returns (bool ok);
|
||||
function approve(address spender, uint value) returns (bool ok);
|
||||
event Transfer(address indexed from, address indexed to, uint value);
|
||||
function transferFrom(address from, address to, uint value);
|
||||
function approve(address spender, uint value);
|
||||
event Approval(address indexed owner, address indexed spender, uint value);
|
||||
}
|
||||
|
||||
@ -4,15 +4,15 @@ import "./ERC20.sol";
|
||||
|
||||
/*
|
||||
|
||||
TransferableToken defines the generic interface and the implementation
|
||||
LimitedTransferToken defines the generic interface and the implementation
|
||||
to limit token transferability for different events.
|
||||
|
||||
It is intended to be used as a base class for other token contracts.
|
||||
|
||||
Over-writting transferableTokens(address holder, uint64 time) is the way to provide
|
||||
the specific logic for limitting token transferability for a holder over time.
|
||||
Overwriting transferableTokens(address holder, uint64 time) is the way to provide
|
||||
the specific logic for limiting token transferability for a holder over time.
|
||||
|
||||
TransferableToken has been designed to allow for different limitting factors,
|
||||
LimitedTransferToken has been designed to allow for different limiting factors,
|
||||
this can be achieved by recursively calling super.transferableTokens() until the
|
||||
base class is hit. For example:
|
||||
|
||||
@ -25,7 +25,7 @@ https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/Ve
|
||||
|
||||
*/
|
||||
|
||||
contract TransferableToken is ERC20 {
|
||||
contract LimitedTransferToken is ERC20 {
|
||||
// Checks whether it can transfer or otherwise throws.
|
||||
modifier canTransfer(address _sender, uint _value) {
|
||||
if (_value > transferableTokens(_sender, uint64(now))) throw;
|
||||
@ -33,12 +33,12 @@ contract TransferableToken is ERC20 {
|
||||
}
|
||||
|
||||
// Checks modifier and allows transfer if tokens are not locked.
|
||||
function transfer(address _to, uint _value) canTransfer(msg.sender, _value) returns (bool success) {
|
||||
function transfer(address _to, uint _value) canTransfer(msg.sender, _value) {
|
||||
return super.transfer(_to, _value);
|
||||
}
|
||||
|
||||
// Checks modifier and allows transfer if tokens are not locked.
|
||||
function transferFrom(address _from, address _to, uint _value) canTransfer(_from, _value) returns (bool success) {
|
||||
function transferFrom(address _from, address _to, uint _value) canTransfer(_from, _value) {
|
||||
return super.transferFrom(_from, _to, _value);
|
||||
}
|
||||
|
||||
43
contracts/token/MintableToken.sol
Normal file
43
contracts/token/MintableToken.sol
Normal file
@ -0,0 +1,43 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import './StandardToken.sol';
|
||||
import '../ownership/Ownable.sol';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mintable token
|
||||
*
|
||||
* Simple ERC20 Token example, with mintable token creation
|
||||
* Issue:
|
||||
* https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
|
||||
* Based on code by TokenMarketNet:
|
||||
* https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
|
||||
*/
|
||||
|
||||
contract MintableToken is StandardToken, Ownable {
|
||||
event Mint(address indexed to, uint value);
|
||||
event MintFinished();
|
||||
|
||||
bool public mintingFinished = false;
|
||||
uint public totalSupply = 0;
|
||||
|
||||
modifier canMint() {
|
||||
if(mintingFinished) throw;
|
||||
_;
|
||||
}
|
||||
|
||||
function mint(address _to, uint _amount) onlyOwner canMint returns (bool) {
|
||||
totalSupply = totalSupply.add(_amount);
|
||||
balances[_to] = balances[_to].add(_amount);
|
||||
Mint(_to, _amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function finishMinting() onlyOwner returns (bool) {
|
||||
mintingFinished = true;
|
||||
MintFinished();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
25
contracts/token/PausableToken.sol
Normal file
25
contracts/token/PausableToken.sol
Normal file
@ -0,0 +1,25 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import './StandardToken.sol';
|
||||
import '../lifecycle/Pausable.sol';
|
||||
|
||||
/**
|
||||
* Pausable token
|
||||
*
|
||||
* Simple ERC20 Token example, with pausable token creation
|
||||
* Issue:
|
||||
* https://github.com/OpenZeppelin/zeppelin-solidity/issues/194
|
||||
* Based on code by BCAPtoken:
|
||||
* https://github.com/BCAPtoken/BCAPToken/blob/5cb5e76338cc47343ba9268663a915337c8b268e/sol/BCAPToken.sol#L27
|
||||
**/
|
||||
|
||||
contract PausableToken is Pausable, StandardToken {
|
||||
|
||||
function transfer(address _to, uint _value) whenNotPaused {
|
||||
return super.transfer(_to, _value);
|
||||
}
|
||||
|
||||
function transferFrom(address _from, address _to, uint _value) whenNotPaused {
|
||||
return super.transferFrom(_from, _to, _value);
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
|
||||
import './BasicToken.sol';
|
||||
import './ERC20.sol';
|
||||
import '../SafeMath.sol';
|
||||
|
||||
|
||||
/**
|
||||
@ -12,39 +12,32 @@ import '../SafeMath.sol';
|
||||
* Based on code by FirstBlood:
|
||||
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
|
||||
*/
|
||||
contract StandardToken is ERC20, SafeMath {
|
||||
contract StandardToken is BasicToken, ERC20 {
|
||||
|
||||
mapping(address => uint) balances;
|
||||
mapping (address => mapping (address => uint)) allowed;
|
||||
|
||||
function transfer(address _to, uint _value) returns (bool success) {
|
||||
balances[msg.sender] = safeSub(balances[msg.sender], _value);
|
||||
balances[_to] = safeAdd(balances[_to], _value);
|
||||
Transfer(msg.sender, _to, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(address _from, address _to, uint _value) returns (bool success) {
|
||||
function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) {
|
||||
var _allowance = allowed[_from][msg.sender];
|
||||
|
||||
// Check is not needed because safeSub(_allowance, _value) will already throw if this condition is not met
|
||||
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
|
||||
// if (_value > _allowance) throw;
|
||||
|
||||
balances[_to] = safeAdd(balances[_to], _value);
|
||||
balances[_from] = safeSub(balances[_from], _value);
|
||||
allowed[_from][msg.sender] = safeSub(_allowance, _value);
|
||||
balances[_to] = balances[_to].add(_value);
|
||||
balances[_from] = balances[_from].sub(_value);
|
||||
allowed[_from][msg.sender] = _allowance.sub(_value);
|
||||
Transfer(_from, _to, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function balanceOf(address _owner) constant returns (uint balance) {
|
||||
return balances[_owner];
|
||||
}
|
||||
function approve(address _spender, uint _value) {
|
||||
|
||||
// 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
|
||||
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw;
|
||||
|
||||
function approve(address _spender, uint _value) returns (bool success) {
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
Approval(msg.sender, _spender, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address _owner, address _spender) constant returns (uint remaining) {
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
pragma solidity ^0.4.8;
|
||||
|
||||
import "./StandardToken.sol";
|
||||
import "./TransferableToken.sol";
|
||||
import "./LimitedTransferToken.sol";
|
||||
|
||||
contract VestedToken is StandardToken, LimitedTransferToken {
|
||||
|
||||
contract VestedToken is StandardToken, TransferableToken {
|
||||
struct TokenGrant {
|
||||
address granter; // 20 bytes
|
||||
uint256 value; // 32 bytes
|
||||
@ -70,11 +71,12 @@ contract VestedToken is StandardToken, TransferableToken {
|
||||
grants[_holder][_grantId] = grants[_holder][grants[_holder].length - 1];
|
||||
grants[_holder].length -= 1;
|
||||
|
||||
balances[receiver] = safeAdd(balances[receiver], nonVested);
|
||||
balances[_holder] = safeSub(balances[_holder], nonVested);
|
||||
balances[receiver] = SafeMath.add(balances[receiver], nonVested);
|
||||
balances[_holder] = SafeMath.sub(balances[_holder], nonVested);
|
||||
Transfer(_holder, receiver, nonVested);
|
||||
}
|
||||
|
||||
|
||||
function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
|
||||
uint256 grantIndex = tokenGrantsCount(holder);
|
||||
|
||||
@ -83,15 +85,15 @@ contract VestedToken is StandardToken, TransferableToken {
|
||||
// Iterate through all the grants the holder has, and add all non-vested tokens
|
||||
uint256 nonVested = 0;
|
||||
for (uint256 i = 0; i < grantIndex; i++) {
|
||||
nonVested = safeAdd(nonVested, nonVestedTokens(grants[holder][i], time));
|
||||
nonVested = SafeMath.add(nonVested, nonVestedTokens(grants[holder][i], time));
|
||||
}
|
||||
|
||||
// Balance - totalNonVested is the amount of tokens a holder can transfer at any given time
|
||||
uint256 vestedTransferable = safeSub(balanceOf(holder), nonVested);
|
||||
uint256 vestedTransferable = SafeMath.sub(balanceOf(holder), nonVested);
|
||||
|
||||
// Return the minimum of how many vested can transfer and other value
|
||||
// in case there are other limiting transferability factors (default is balanceOf)
|
||||
return min256(vestedTransferable, super.transferableTokens(holder, time));
|
||||
return SafeMath.min256(vestedTransferable, super.transferableTokens(holder, time));
|
||||
}
|
||||
|
||||
function tokenGrantsCount(address _holder) constant returns (uint index) {
|
||||
@ -129,12 +131,12 @@ contract VestedToken is StandardToken, TransferableToken {
|
||||
// in the vesting rect (as shown in above's figure)
|
||||
|
||||
// vestedTokens = tokens * (time - start) / (vesting - start)
|
||||
uint256 vestedTokens = safeDiv(
|
||||
safeMul(
|
||||
uint256 vestedTokens = SafeMath.div(
|
||||
SafeMath.mul(
|
||||
tokens,
|
||||
safeSub(time, start)
|
||||
SafeMath.sub(time, start)
|
||||
),
|
||||
safeSub(vesting, start)
|
||||
SafeMath.sub(vesting, start)
|
||||
);
|
||||
|
||||
return vestedTokens;
|
||||
@ -165,14 +167,14 @@ contract VestedToken is StandardToken, TransferableToken {
|
||||
}
|
||||
|
||||
function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
|
||||
return safeSub(grant.value, vestedTokens(grant, time));
|
||||
return grant.value.sub(vestedTokens(grant, time));
|
||||
}
|
||||
|
||||
function lastTokenIsTransferableDate(address holder) constant public returns (uint64 date) {
|
||||
date = uint64(now);
|
||||
uint256 grantIndex = grants[holder].length;
|
||||
for (uint256 i = 0; i < grantIndex; i++) {
|
||||
date = max64(grants[holder][i].vesting, date);
|
||||
date = SafeMath.max64(grants[holder][i].vesting, date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user