From ac84b36144f746662e5ddb984d283e053c7d06ba Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 5 Jul 2017 12:28:15 +0200 Subject: Added various contracts for testing. --- test/compilationTests/zeppelin/Bounty.sol | 78 +++++++ test/compilationTests/zeppelin/DayLimit.sol | 75 +++++++ test/compilationTests/zeppelin/LICENSE | 22 ++ test/compilationTests/zeppelin/LimitBalance.sol | 33 +++ test/compilationTests/zeppelin/MultisigWallet.sol | 127 +++++++++++ test/compilationTests/zeppelin/README.md | 3 + test/compilationTests/zeppelin/ReentrancyGuard.sol | 34 +++ .../zeppelin/crowdsale/CappedCrowdsale.sol | 33 +++ .../zeppelin/crowdsale/Crowdsale.sol | 108 +++++++++ .../zeppelin/crowdsale/FinalizableCrowdsale.sol | 39 ++++ .../zeppelin/crowdsale/RefundVault.sol | 56 +++++ .../zeppelin/crowdsale/RefundableCrowdsale.sol | 59 +++++ .../zeppelin/lifecycle/Destructible.sol | 25 +++ .../zeppelin/lifecycle/Migrations.sol | 21 ++ .../zeppelin/lifecycle/Pausable.sol | 51 +++++ .../zeppelin/lifecycle/TokenDestructible.sol | 36 +++ test/compilationTests/zeppelin/math/Math.sol | 24 ++ test/compilationTests/zeppelin/math/SafeMath.sol | 32 +++ .../zeppelin/ownership/Claimable.sol | 40 ++++ .../zeppelin/ownership/Contactable.sol | 21 ++ .../zeppelin/ownership/DelayedClaimable.sol | 43 ++++ .../zeppelin/ownership/HasNoContracts.sol | 21 ++ .../zeppelin/ownership/HasNoEther.sol | 44 ++++ .../zeppelin/ownership/HasNoTokens.sol | 34 +++ .../zeppelin/ownership/Multisig.sol | 28 +++ .../zeppelin/ownership/NoOwner.sol | 14 ++ .../zeppelin/ownership/Ownable.sol | 43 ++++ .../zeppelin/ownership/Shareable.sol | 189 ++++++++++++++++ .../zeppelin/payment/PullPayment.sol | 50 +++++ .../compilationTests/zeppelin/token/BasicToken.sol | 37 +++ test/compilationTests/zeppelin/token/ERC20.sol | 16 ++ .../compilationTests/zeppelin/token/ERC20Basic.sol | 14 ++ .../zeppelin/token/LimitedTransferToken.sol | 57 +++++ .../zeppelin/token/MintableToken.sol | 50 +++++ .../zeppelin/token/PausableToken.sol | 21 ++ .../zeppelin/token/SimpleToken.sol | 28 +++ .../zeppelin/token/StandardToken.sol | 65 ++++++ .../zeppelin/token/TokenTimelock.sol | 41 ++++ .../zeppelin/token/VestedToken.sol | 248 +++++++++++++++++++++ 39 files changed, 1960 insertions(+) create mode 100644 test/compilationTests/zeppelin/Bounty.sol create mode 100644 test/compilationTests/zeppelin/DayLimit.sol create mode 100644 test/compilationTests/zeppelin/LICENSE create mode 100644 test/compilationTests/zeppelin/LimitBalance.sol create mode 100644 test/compilationTests/zeppelin/MultisigWallet.sol create mode 100644 test/compilationTests/zeppelin/README.md create mode 100644 test/compilationTests/zeppelin/ReentrancyGuard.sol create mode 100644 test/compilationTests/zeppelin/crowdsale/CappedCrowdsale.sol create mode 100644 test/compilationTests/zeppelin/crowdsale/Crowdsale.sol create mode 100644 test/compilationTests/zeppelin/crowdsale/FinalizableCrowdsale.sol create mode 100644 test/compilationTests/zeppelin/crowdsale/RefundVault.sol create mode 100644 test/compilationTests/zeppelin/crowdsale/RefundableCrowdsale.sol create mode 100644 test/compilationTests/zeppelin/lifecycle/Destructible.sol create mode 100644 test/compilationTests/zeppelin/lifecycle/Migrations.sol create mode 100644 test/compilationTests/zeppelin/lifecycle/Pausable.sol create mode 100644 test/compilationTests/zeppelin/lifecycle/TokenDestructible.sol create mode 100644 test/compilationTests/zeppelin/math/Math.sol create mode 100644 test/compilationTests/zeppelin/math/SafeMath.sol create mode 100644 test/compilationTests/zeppelin/ownership/Claimable.sol create mode 100644 test/compilationTests/zeppelin/ownership/Contactable.sol create mode 100644 test/compilationTests/zeppelin/ownership/DelayedClaimable.sol create mode 100644 test/compilationTests/zeppelin/ownership/HasNoContracts.sol create mode 100644 test/compilationTests/zeppelin/ownership/HasNoEther.sol create mode 100644 test/compilationTests/zeppelin/ownership/HasNoTokens.sol create mode 100644 test/compilationTests/zeppelin/ownership/Multisig.sol create mode 100644 test/compilationTests/zeppelin/ownership/NoOwner.sol create mode 100644 test/compilationTests/zeppelin/ownership/Ownable.sol create mode 100644 test/compilationTests/zeppelin/ownership/Shareable.sol create mode 100644 test/compilationTests/zeppelin/payment/PullPayment.sol create mode 100644 test/compilationTests/zeppelin/token/BasicToken.sol create mode 100644 test/compilationTests/zeppelin/token/ERC20.sol create mode 100644 test/compilationTests/zeppelin/token/ERC20Basic.sol create mode 100644 test/compilationTests/zeppelin/token/LimitedTransferToken.sol create mode 100644 test/compilationTests/zeppelin/token/MintableToken.sol create mode 100644 test/compilationTests/zeppelin/token/PausableToken.sol create mode 100644 test/compilationTests/zeppelin/token/SimpleToken.sol create mode 100644 test/compilationTests/zeppelin/token/StandardToken.sol create mode 100644 test/compilationTests/zeppelin/token/TokenTimelock.sol create mode 100644 test/compilationTests/zeppelin/token/VestedToken.sol (limited to 'test/compilationTests/zeppelin') diff --git a/test/compilationTests/zeppelin/Bounty.sol b/test/compilationTests/zeppelin/Bounty.sol new file mode 100644 index 00000000..4425b7a5 --- /dev/null +++ b/test/compilationTests/zeppelin/Bounty.sol @@ -0,0 +1,78 @@ +pragma solidity ^0.4.11; + + +import './payment/PullPayment.sol'; +import './lifecycle/Destructible.sol'; + + +/** + * @title Bounty + * @dev This bounty will pay out to a researcher if they break invariant logic of the contract. + */ +contract Bounty is PullPayment, Destructible { + bool public claimed; + mapping(address => address) public researchers; + + event TargetCreated(address createdAddress); + + /** + * @dev Fallback function allowing the contract to recieve funds, if they haven't already been claimed. + */ + function() payable { + if (claimed) { + throw; + } + } + + /** + * @dev Create and deploy the target contract (extension of Target contract), and sets the + * msg.sender as a researcher + * @return A target contract + */ + function createTarget() returns(Target) { + Target target = Target(deployContract()); + researchers[target] = msg.sender; + TargetCreated(target); + return target; + } + + /** + * @dev Internal function to deploy the target contract. + * @return A target contract address + */ + function deployContract() internal returns(address); + + /** + * @dev Sends the contract funds to the researcher that proved the contract is broken. + * @param target contract + */ + function claim(Target target) { + address researcher = researchers[target]; + if (researcher == 0) { + throw; + } + // Check Target contract invariants + if (target.checkInvariant()) { + throw; + } + asyncSend(researcher, this.balance); + claimed = true; + } + +} + + +/** + * @title Target + * @dev Your main contract should inherit from this class and implement the checkInvariant method. + */ +contract Target { + + /** + * @dev Checks all values a contract assumes to be true all the time. If this function returns + * false, the contract is broken in some way and is in an inconsistent state. + * In order to win the bounty, security researchers will try to cause this broken state. + * @return True if all invariant values are correct, false otherwise. + */ + function checkInvariant() returns(bool); +} diff --git a/test/compilationTests/zeppelin/DayLimit.sol b/test/compilationTests/zeppelin/DayLimit.sol new file mode 100644 index 00000000..3c8d5b0c --- /dev/null +++ b/test/compilationTests/zeppelin/DayLimit.sol @@ -0,0 +1,75 @@ +pragma solidity ^0.4.11; + +/** + * @title DayLimit + * @dev Base contract that enables methods to be protected by placing a linear limit (specifiable) + * on a particular resource per calendar day. Is multiowned to allow the limit to be altered. + */ +contract DayLimit { + + uint256 public dailyLimit; + uint256 public spentToday; + uint256 public lastDay; + + /** + * @dev Constructor that sets the passed value as a dailyLimit. + * @param _limit uint256 to represent the daily limit. + */ + function DayLimit(uint256 _limit) { + dailyLimit = _limit; + lastDay = today(); + } + + /** + * @dev sets the daily limit. Does not alter the amount already spent today. + * @param _newLimit uint256 to represent the new limit. + */ + function _setDailyLimit(uint256 _newLimit) internal { + dailyLimit = _newLimit; + } + + /** + * @dev Resets the amount already spent today. + */ + function _resetSpentToday() internal { + spentToday = 0; + } + + /** + * @dev Checks to see if there is enough resource to spend today. If true, the resource may be expended. + * @param _value uint256 representing the amount of resource to spend. + * @return A boolean that is True if the resource was spended and false otherwise. + */ + function underLimit(uint256 _value) internal returns (bool) { + // reset the spend limit if we're on a different day to last time. + if (today() > lastDay) { + spentToday = 0; + lastDay = today(); + } + // check to see if there's enough left - if so, subtract and return true. + // overflow protection // dailyLimit check + if (spentToday + _value >= spentToday && spentToday + _value <= dailyLimit) { + spentToday += _value; + return true; + } + return false; + } + + /** + * @dev Private function to determine today's index + * @return uint256 of today's index. + */ + function today() private constant returns (uint256) { + return now / 1 days; + } + + /** + * @dev Simple modifier for daily limit. + */ + modifier limitedDaily(uint256 _value) { + if (!underLimit(_value)) { + throw; + } + _; + } +} diff --git a/test/compilationTests/zeppelin/LICENSE b/test/compilationTests/zeppelin/LICENSE new file mode 100644 index 00000000..85f53321 --- /dev/null +++ b/test/compilationTests/zeppelin/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 Smart Contract Solutions, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test/compilationTests/zeppelin/LimitBalance.sol b/test/compilationTests/zeppelin/LimitBalance.sol new file mode 100644 index 00000000..57477c74 --- /dev/null +++ b/test/compilationTests/zeppelin/LimitBalance.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.4.11; + + +/** + * @title LimitBalance + * @dev Simple contract to limit the balance of child contract. + * @dev Note this doesn't prevent other contracts to send funds by using selfdestruct(address); + * @dev See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account + */ +contract LimitBalance { + + uint256 public limit; + + /** + * @dev Constructor that sets the passed value as a limit. + * @param _limit uint256 to represent the limit. + */ + function LimitBalance(uint256 _limit) { + limit = _limit; + } + + /** + * @dev Checks if limit was reached. Case true, it throws. + */ + modifier limitedPayable() { + if (this.balance > limit) { + throw; + } + _; + + } + +} diff --git a/test/compilationTests/zeppelin/MultisigWallet.sol b/test/compilationTests/zeppelin/MultisigWallet.sol new file mode 100644 index 00000000..939e70f2 --- /dev/null +++ b/test/compilationTests/zeppelin/MultisigWallet.sol @@ -0,0 +1,127 @@ +pragma solidity ^0.4.11; + + +import "./ownership/Multisig.sol"; +import "./ownership/Shareable.sol"; +import "./DayLimit.sol"; + + +/** + * MultisigWallet + * Usage: + * bytes32 h = Wallet(w).from(oneOwner).execute(to, value, data); + * Wallet(w).from(anotherOwner).confirm(h); + */ +contract MultisigWallet is Multisig, Shareable, DayLimit { + + struct Transaction { + address to; + uint256 value; + bytes data; + } + + /** + * Constructor, sets the owners addresses, number of approvals required, and daily spending limit + * @param _owners A list of owners. + * @param _required The amount required for a transaction to be approved. + */ + function MultisigWallet(address[] _owners, uint256 _required, uint256 _daylimit) + Shareable(_owners, _required) + DayLimit(_daylimit) { } + + /** + * @dev destroys the contract sending everything to `_to`. + */ + function destroy(address _to) onlymanyowners(keccak256(msg.data)) external { + selfdestruct(_to); + } + + /** + * @dev Fallback function, receives value and emits a deposit event. + */ + function() payable { + // just being sent some cash? + if (msg.value > 0) + Deposit(msg.sender, msg.value); + } + + /** + * @dev Outside-visible transaction entry point. Executes transaction immediately if below daily + * spending limit. If not, goes into multisig process. We provide a hash on return to allow the + * sender to provide shortcuts for the other confirmations (allowing them to avoid replicating + * the _to, _value, and _data arguments). They still get the option of using them if they want, + * anyways. + * @param _to The receiver address + * @param _value The value to send + * @param _data The data part of the transaction + */ + function execute(address _to, uint256 _value, bytes _data) external onlyOwner returns (bytes32 _r) { + // first, take the opportunity to check that we're under the daily limit. + if (underLimit(_value)) { + SingleTransact(msg.sender, _value, _to, _data); + // yes - just execute the call. + if (!_to.call.value(_value)(_data)) { + throw; + } + return 0; + } + // determine our operation hash. + _r = keccak256(msg.data, block.number); + if (!confirm(_r) && txs[_r].to == 0) { + txs[_r].to = _to; + txs[_r].value = _value; + txs[_r].data = _data; + ConfirmationNeeded(_r, msg.sender, _value, _to, _data); + } + } + + /** + * @dev Confirm a transaction by providing just the hash. We use the previous transactions map, + * txs, in order to determine the body of the transaction from the hash provided. + * @param _h The transaction hash to approve. + */ + function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) { + if (txs[_h].to != 0) { + if (!txs[_h].to.call.value(txs[_h].value)(txs[_h].data)) { + throw; + } + MultiTransact(msg.sender, _h, txs[_h].value, txs[_h].to, txs[_h].data); + delete txs[_h]; + return true; + } + } + + /** + * @dev Updates the daily limit value. + * @param _newLimit uint256 to represent the new limit. + */ + function setDailyLimit(uint256 _newLimit) onlymanyowners(keccak256(msg.data)) external { + _setDailyLimit(_newLimit); + } + + /** + * @dev Resets the value spent to enable more spending + */ + function resetSpentToday() onlymanyowners(keccak256(msg.data)) external { + _resetSpentToday(); + } + + + // INTERNAL METHODS + /** + * @dev Clears the list of transactions pending approval. + */ + function clearPending() internal { + uint256 length = pendingsIndex.length; + for (uint256 i = 0; i < length; ++i) { + delete txs[pendingsIndex[i]]; + } + super.clearPending(); + } + + + // FIELDS + + // pending transactions we have at present. + mapping (bytes32 => Transaction) txs; +} diff --git a/test/compilationTests/zeppelin/README.md b/test/compilationTests/zeppelin/README.md new file mode 100644 index 00000000..dee2f5ca --- /dev/null +++ b/test/compilationTests/zeppelin/README.md @@ -0,0 +1,3 @@ +Zeppelin contracts, originally from + +https://github.com/OpenZeppelin/zeppelin-solidity diff --git a/test/compilationTests/zeppelin/ReentrancyGuard.sol b/test/compilationTests/zeppelin/ReentrancyGuard.sol new file mode 100644 index 00000000..ca8b643b --- /dev/null +++ b/test/compilationTests/zeppelin/ReentrancyGuard.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.4.11; + +/** + * @title Helps contracts guard agains rentrancy attacks. + * @author Remco Bloemen + * @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; + + /** + * @dev Prevents a 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; + } + } + +} diff --git a/test/compilationTests/zeppelin/crowdsale/CappedCrowdsale.sol b/test/compilationTests/zeppelin/crowdsale/CappedCrowdsale.sol new file mode 100644 index 00000000..f04649f3 --- /dev/null +++ b/test/compilationTests/zeppelin/crowdsale/CappedCrowdsale.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.4.11; + +import '../math/SafeMath.sol'; +import './Crowdsale.sol'; + +/** + * @title CappedCrowdsale + * @dev Extension of Crowsdale with a max amount of funds raised + */ +contract CappedCrowdsale is Crowdsale { + using SafeMath for uint256; + + uint256 public cap; + + function CappedCrowdsale(uint256 _cap) { + cap = _cap; + } + + // overriding Crowdsale#validPurchase to add extra cap logic + // @return true if investors can buy at the moment + function validPurchase() internal constant returns (bool) { + bool withinCap = weiRaised.add(msg.value) <= cap; + return super.validPurchase() && withinCap; + } + + // overriding Crowdsale#hasEnded to add cap logic + // @return true if crowdsale event has ended + function hasEnded() public constant returns (bool) { + bool capReached = weiRaised >= cap; + return super.hasEnded() || capReached; + } + +} diff --git a/test/compilationTests/zeppelin/crowdsale/Crowdsale.sol b/test/compilationTests/zeppelin/crowdsale/Crowdsale.sol new file mode 100644 index 00000000..bee1efd2 --- /dev/null +++ b/test/compilationTests/zeppelin/crowdsale/Crowdsale.sol @@ -0,0 +1,108 @@ +pragma solidity ^0.4.11; + +import '../token/MintableToken.sol'; +import '../math/SafeMath.sol'; + +/** + * @title Crowdsale + * @dev Crowdsale is a base contract for managing a token crowdsale. + * Crowdsales have a start and end block, where investors can make + * token purchases and the crowdsale will assign them tokens based + * on a token per ETH rate. Funds collected are forwarded to a wallet + * as they arrive. + */ +contract Crowdsale { + using SafeMath for uint256; + + // The token being sold + MintableToken public token; + + // start and end block where investments are allowed (both inclusive) + uint256 public startBlock; + uint256 public endBlock; + + // address where funds are collected + address public wallet; + + // how many token units a buyer gets per wei + uint256 public rate; + + // amount of raised money in wei + uint256 public weiRaised; + + /** + * event for token purchase logging + * @param purchaser who paid for the tokens + * @param beneficiary who got the tokens + * @param value weis paid for purchase + * @param amount amount of tokens purchased + */ + event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount); + + + function Crowdsale(uint256 _startBlock, uint256 _endBlock, uint256 _rate, address _wallet) { + require(_startBlock >= block.number); + require(_endBlock >= _startBlock); + require(_rate > 0); + require(_wallet != 0x0); + + token = createTokenContract(); + startBlock = _startBlock; + endBlock = _endBlock; + rate = _rate; + wallet = _wallet; + } + + // creates the token to be sold. + // override this method to have crowdsale of a specific mintable token. + function createTokenContract() internal returns (MintableToken) { + return new MintableToken(); + } + + + // fallback function can be used to buy tokens + function () payable { + buyTokens(msg.sender); + } + + // low level token purchase function + function buyTokens(address beneficiary) payable { + require(beneficiary != 0x0); + require(validPurchase()); + + uint256 weiAmount = msg.value; + uint256 updatedWeiRaised = weiRaised.add(weiAmount); + + // calculate token amount to be created + uint256 tokens = weiAmount.mul(rate); + + // update state + weiRaised = updatedWeiRaised; + + token.mint(beneficiary, tokens); + TokenPurchase(msg.sender, beneficiary, weiAmount, tokens); + + forwardFunds(); + } + + // send ether to the fund collection wallet + // override to create custom fund forwarding mechanisms + function forwardFunds() internal { + wallet.transfer(msg.value); + } + + // @return true if the transaction can buy tokens + function validPurchase() internal constant returns (bool) { + uint256 current = block.number; + bool withinPeriod = current >= startBlock && current <= endBlock; + bool nonZeroPurchase = msg.value != 0; + return withinPeriod && nonZeroPurchase; + } + + // @return true if crowdsale event has ended + function hasEnded() public constant returns (bool) { + return block.number > endBlock; + } + + +} diff --git a/test/compilationTests/zeppelin/crowdsale/FinalizableCrowdsale.sol b/test/compilationTests/zeppelin/crowdsale/FinalizableCrowdsale.sol new file mode 100644 index 00000000..1a736083 --- /dev/null +++ b/test/compilationTests/zeppelin/crowdsale/FinalizableCrowdsale.sol @@ -0,0 +1,39 @@ +pragma solidity ^0.4.11; + +import '../math/SafeMath.sol'; +import '../ownership/Ownable.sol'; +import './Crowdsale.sol'; + +/** + * @title FinalizableCrowdsale + * @dev Extension of Crowsdale where an owner can do extra work + * after finishing. By default, it will end token minting. + */ +contract FinalizableCrowdsale is Crowdsale, Ownable { + using SafeMath for uint256; + + bool public isFinalized = false; + + event Finalized(); + + // should be called after crowdsale ends, to do + // some extra finalization work + function finalize() onlyOwner { + require(!isFinalized); + require(hasEnded()); + + finalization(); + Finalized(); + + isFinalized = true; + } + + // end token minting on finalization + // override this with custom logic if needed + function finalization() internal { + token.finishMinting(); + } + + + +} diff --git a/test/compilationTests/zeppelin/crowdsale/RefundVault.sol b/test/compilationTests/zeppelin/crowdsale/RefundVault.sol new file mode 100644 index 00000000..cc92ff9f --- /dev/null +++ b/test/compilationTests/zeppelin/crowdsale/RefundVault.sol @@ -0,0 +1,56 @@ +pragma solidity ^0.4.11; + +import '../math/SafeMath.sol'; +import '../ownership/Ownable.sol'; + +/** + * @title RefundVault + * @dev This contract is used for storing funds while a crowdsale + * is in progress. Supports refunding the money if crowdsale fails, + * and forwarding it if crowdsale is successful. + */ +contract RefundVault is Ownable { + using SafeMath for uint256; + + enum State { Active, Refunding, Closed } + + mapping (address => uint256) public deposited; + address public wallet; + State public state; + + event Closed(); + event RefundsEnabled(); + event Refunded(address indexed beneficiary, uint256 weiAmount); + + function RefundVault(address _wallet) { + require(_wallet != 0x0); + wallet = _wallet; + state = State.Active; + } + + function deposit(address investor) onlyOwner payable { + require(state == State.Active); + deposited[investor] = deposited[investor].add(msg.value); + } + + function close() onlyOwner { + require(state == State.Active); + state = State.Closed; + Closed(); + wallet.transfer(this.balance); + } + + function enableRefunds() onlyOwner { + require(state == State.Active); + state = State.Refunding; + RefundsEnabled(); + } + + function refund(address investor) { + require(state == State.Refunding); + uint256 depositedValue = deposited[investor]; + deposited[investor] = 0; + investor.transfer(depositedValue); + Refunded(investor, depositedValue); + } +} diff --git a/test/compilationTests/zeppelin/crowdsale/RefundableCrowdsale.sol b/test/compilationTests/zeppelin/crowdsale/RefundableCrowdsale.sol new file mode 100644 index 00000000..f45df1d3 --- /dev/null +++ b/test/compilationTests/zeppelin/crowdsale/RefundableCrowdsale.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.4.11; + + +import '../math/SafeMath.sol'; +import './FinalizableCrowdsale.sol'; +import './RefundVault.sol'; + + +/** + * @title RefundableCrowdsale + * @dev Extension of Crowdsale contract that adds a funding goal, and + * the possibility of users getting a refund if goal is not met. + * Uses a RefundVault as the crowdsale's vault. + */ +contract RefundableCrowdsale is FinalizableCrowdsale { + using SafeMath for uint256; + + // minimum amount of funds to be raised in weis + uint256 public goal; + + // refund vault used to hold funds while crowdsale is running + RefundVault public vault; + + function RefundableCrowdsale(uint256 _goal) { + vault = new RefundVault(wallet); + goal = _goal; + } + + // We're overriding the fund forwarding from Crowdsale. + // In addition to sending the funds, we want to call + // the RefundVault deposit function + function forwardFunds() internal { + vault.deposit.value(msg.value)(msg.sender); + } + + // if crowdsale is unsuccessful, investors can claim refunds here + function claimRefund() { + require(isFinalized); + require(!goalReached()); + + vault.refund(msg.sender); + } + + // vault finalization task, called when owner calls finalize() + function finalization() internal { + if (goalReached()) { + vault.close(); + } else { + vault.enableRefunds(); + } + + super.finalization(); + } + + function goalReached() public constant returns (bool) { + return weiRaised >= goal; + } + +} diff --git a/test/compilationTests/zeppelin/lifecycle/Destructible.sol b/test/compilationTests/zeppelin/lifecycle/Destructible.sol new file mode 100644 index 00000000..3561e3b7 --- /dev/null +++ b/test/compilationTests/zeppelin/lifecycle/Destructible.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.4.11; + + +import "../ownership/Ownable.sol"; + + +/** + * @title Destructible + * @dev Base contract that can be destroyed by owner. All funds in contract will be sent to the owner. + */ +contract Destructible is Ownable { + + function Destructible() payable { } + + /** + * @dev Transfers the current balance to the owner and terminates the contract. + */ + function destroy() onlyOwner { + selfdestruct(owner); + } + + function destroyAndSend(address _recipient) onlyOwner { + selfdestruct(_recipient); + } +} diff --git a/test/compilationTests/zeppelin/lifecycle/Migrations.sol b/test/compilationTests/zeppelin/lifecycle/Migrations.sol new file mode 100644 index 00000000..d5b05308 --- /dev/null +++ b/test/compilationTests/zeppelin/lifecycle/Migrations.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.11; + + +import '../ownership/Ownable.sol'; + +/** + * @title Migrations + * @dev This is a truffle contract, needed for truffle integration, not meant for use by Zeppelin users. + */ +contract Migrations is Ownable { + uint256 public lastCompletedMigration; + + function setCompleted(uint256 completed) onlyOwner { + lastCompletedMigration = completed; + } + + function upgrade(address newAddress) onlyOwner { + Migrations upgraded = Migrations(newAddress); + upgraded.setCompleted(lastCompletedMigration); + } +} diff --git a/test/compilationTests/zeppelin/lifecycle/Pausable.sol b/test/compilationTests/zeppelin/lifecycle/Pausable.sol new file mode 100644 index 00000000..b14f8767 --- /dev/null +++ b/test/compilationTests/zeppelin/lifecycle/Pausable.sol @@ -0,0 +1,51 @@ +pragma solidity ^0.4.11; + + +import "../ownership/Ownable.sol"; + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + if (paused) throw; + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + if (!paused) throw; + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused returns (bool) { + paused = true; + Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused returns (bool) { + paused = false; + Unpause(); + return true; + } +} diff --git a/test/compilationTests/zeppelin/lifecycle/TokenDestructible.sol b/test/compilationTests/zeppelin/lifecycle/TokenDestructible.sol new file mode 100644 index 00000000..fe0b46b6 --- /dev/null +++ b/test/compilationTests/zeppelin/lifecycle/TokenDestructible.sol @@ -0,0 +1,36 @@ +pragma solidity ^0.4.11; + + +import "../ownership/Ownable.sol"; +import "../token/ERC20Basic.sol"; + +/** + * @title TokenDestructible: + * @author Remco Bloemen + * @dev 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 { + + function TokenDestructible() payable { } + + /** + * @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 trust. + */ + function destroy(address[] tokens) onlyOwner { + + // Transfer tokens to owner + for(uint256 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); + } +} diff --git a/test/compilationTests/zeppelin/math/Math.sol b/test/compilationTests/zeppelin/math/Math.sol new file mode 100644 index 00000000..3d016c0a --- /dev/null +++ b/test/compilationTests/zeppelin/math/Math.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.11; + +/** + * @title Math + * @dev Assorted math operations + */ + +library Math { + function max64(uint64 a, uint64 b) internal constant returns (uint64) { + return a >= b ? a : b; + } + + function min64(uint64 a, uint64 b) internal constant returns (uint64) { + return a < b ? a : b; + } + + function max256(uint256 a, uint256 b) internal constant returns (uint256) { + return a >= b ? a : b; + } + + function min256(uint256 a, uint256 b) internal constant returns (uint256) { + return a < b ? a : b; + } +} diff --git a/test/compilationTests/zeppelin/math/SafeMath.sol b/test/compilationTests/zeppelin/math/SafeMath.sol new file mode 100644 index 00000000..dc05ba28 --- /dev/null +++ b/test/compilationTests/zeppelin/math/SafeMath.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.11; + + +/** + * @title SafeMath + * @dev Math operations with safety checks that throw on error + */ +library SafeMath { + function mul(uint256 a, uint256 b) internal returns (uint256) { + uint256 c = a * b; + assert(a == 0 || c / a == b); + return c; + } + + function div(uint256 a, uint256 b) internal returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return c; + } + + function sub(uint256 a, uint256 b) internal returns (uint256) { + assert(b <= a); + return a - b; + } + + function add(uint256 a, uint256 b) internal returns (uint256) { + uint256 c = a + b; + assert(c >= a); + return c; + } +} diff --git a/test/compilationTests/zeppelin/ownership/Claimable.sol b/test/compilationTests/zeppelin/ownership/Claimable.sol new file mode 100644 index 00000000..d063502d --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/Claimable.sol @@ -0,0 +1,40 @@ +pragma solidity ^0.4.11; + + +import './Ownable.sol'; + + +/** + * @title Claimable + * @dev Extension for the Ownable contract, where the ownership needs to be claimed. + * This allows the new owner to accept the transfer. + */ +contract Claimable is Ownable { + address public pendingOwner; + + /** + * @dev Modifier throws if called by any account other than the pendingOwner. + */ + modifier onlyPendingOwner() { + if (msg.sender != pendingOwner) { + throw; + } + _; + } + + /** + * @dev Allows the current owner to set the pendingOwner address. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) onlyOwner { + pendingOwner = newOwner; + } + + /** + * @dev Allows the pendingOwner address to finalize the transfer. + */ + function claimOwnership() onlyPendingOwner { + owner = pendingOwner; + pendingOwner = 0x0; + } +} diff --git a/test/compilationTests/zeppelin/ownership/Contactable.sol b/test/compilationTests/zeppelin/ownership/Contactable.sol new file mode 100644 index 00000000..0db3ee07 --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/Contactable.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.11; + +import './Ownable.sol'; + +/** + * @title Contactable token + * @dev Basic version of a contactable contract, allowing the owner to provide a string with their + * contact information. + */ +contract Contactable is Ownable{ + + string public contactInformation; + + /** + * @dev Allows the owner to set a string with their contact information. + * @param info The contact information to attach to the contract. + */ + function setContactInformation(string info) onlyOwner{ + contactInformation = info; + } +} diff --git a/test/compilationTests/zeppelin/ownership/DelayedClaimable.sol b/test/compilationTests/zeppelin/ownership/DelayedClaimable.sol new file mode 100644 index 00000000..f5fee614 --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/DelayedClaimable.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.4.11; + + +import './Claimable.sol'; + + +/** + * @title DelayedClaimable + * @dev Extension for the Claimable contract, where the ownership needs to be claimed before/after + * a certain block number. + */ +contract DelayedClaimable is Claimable { + + uint256 public end; + uint256 public start; + + /** + * @dev Used to specify the time period during which a pending + * owner can claim ownership. + * @param _start The earliest time ownership can be claimed. + * @param _end The latest time ownership can be claimed. + */ + function setLimits(uint256 _start, uint256 _end) onlyOwner { + if (_start > _end) + throw; + end = _end; + start = _start; + } + + + /** + * @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within + * the specified start and end time. + */ + function claimOwnership() onlyPendingOwner { + if ((block.number > end) || (block.number < start)) + throw; + owner = pendingOwner; + pendingOwner = 0x0; + end = 0; + } + +} diff --git a/test/compilationTests/zeppelin/ownership/HasNoContracts.sol b/test/compilationTests/zeppelin/ownership/HasNoContracts.sol new file mode 100644 index 00000000..b5bd649d --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/HasNoContracts.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.11; + +import "./Ownable.sol"; + +/** + * @title Contracts that should not own Contracts + * @author Remco Bloemen + * @dev 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 { + + /** + * @dev Reclaim ownership of Ownable contracts + * @param contractAddr The address of the Ownable to be reclaimed. + */ + function reclaimContract(address contractAddr) external onlyOwner { + Ownable contractInst = Ownable(contractAddr); + contractInst.transferOwnership(owner); + } +} diff --git a/test/compilationTests/zeppelin/ownership/HasNoEther.sol b/test/compilationTests/zeppelin/ownership/HasNoEther.sol new file mode 100644 index 00000000..2bcaf1b8 --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/HasNoEther.sol @@ -0,0 +1,44 @@ +pragma solidity ^0.4.11; + +import "./Ownable.sol"; + +/** + * @title Contracts that should not own Ether + * @author Remco Bloemen + * @dev This tries to block incoming ether to prevent accidental loss of Ether. Should Ether end up + * in the contract, 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 { + + /** + * @dev Constructor that rejects incoming Ether + * @dev The `payable` flag 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; + } + } + + /** + * @dev Disallows direct send by settings a default function without the `payable` flag. + */ + function() external { + } + + /** + * @dev Transfer all Ether held by the contract to the owner. + */ + function reclaimEther() external onlyOwner { + if(!owner.send(this.balance)) { + throw; + } + } +} diff --git a/test/compilationTests/zeppelin/ownership/HasNoTokens.sol b/test/compilationTests/zeppelin/ownership/HasNoTokens.sol new file mode 100644 index 00000000..d1dc4b3e --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/HasNoTokens.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.4.11; + +import "./Ownable.sol"; +import "../token/ERC20Basic.sol"; + +/** + * @title Contracts that should not own Tokens + * @author Remco Bloemen + * @dev 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 { + + /** + * @dev Reject all ERC23 compatible tokens + * @param from_ address The address that is transferring the tokens + * @param value_ uint256 the amount of the specified token + * @param data_ Bytes The data passed from the caller. + */ + function tokenFallback(address from_, uint256 value_, bytes data_) external { + throw; + } + + /** + * @dev Reclaim all ERC20Basic compatible tokens + * @param tokenAddr address The address of the token contract + */ + function reclaimToken(address tokenAddr) external onlyOwner { + ERC20Basic tokenInst = ERC20Basic(tokenAddr); + uint256 balance = tokenInst.balanceOf(this); + tokenInst.transfer(owner, balance); + } +} diff --git a/test/compilationTests/zeppelin/ownership/Multisig.sol b/test/compilationTests/zeppelin/ownership/Multisig.sol new file mode 100644 index 00000000..76c78411 --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/Multisig.sol @@ -0,0 +1,28 @@ +pragma solidity ^0.4.11; + + +/** + * @title Multisig + * @dev Interface contract for multisig proxy contracts; see below for docs. + */ +contract Multisig { + // EVENTS + + // logged events: + // Funds has arrived into the wallet (record how much). + event Deposit(address _from, uint256 value); + // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). + event SingleTransact(address owner, uint256 value, address to, bytes data); + // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). + event MultiTransact(address owner, bytes32 operation, uint256 value, address to, bytes data); + // Confirmation still needed for a transaction. + event ConfirmationNeeded(bytes32 operation, address initiator, uint256 value, address to, bytes data); + + + // FUNCTIONS + + // TODO: document + function changeOwner(address _from, address _to) external; + function execute(address _to, uint256 _value, bytes _data) external returns (bytes32); + function confirm(bytes32 _h) returns (bool); +} diff --git a/test/compilationTests/zeppelin/ownership/NoOwner.sol b/test/compilationTests/zeppelin/ownership/NoOwner.sol new file mode 100644 index 00000000..7215abf3 --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/NoOwner.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.4.11; + +import "./HasNoEther.sol"; +import "./HasNoTokens.sol"; +import "./HasNoContracts.sol"; + +/** + * @title Base contract for contracts that should not own things. + * @author Remco Bloemen + * @dev 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 { +} diff --git a/test/compilationTests/zeppelin/ownership/Ownable.sol b/test/compilationTests/zeppelin/ownership/Ownable.sol new file mode 100644 index 00000000..f1628454 --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/Ownable.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + function Ownable() { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + if (msg.sender != owner) { + throw; + } + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} diff --git a/test/compilationTests/zeppelin/ownership/Shareable.sol b/test/compilationTests/zeppelin/ownership/Shareable.sol new file mode 100644 index 00000000..9fdaccfd --- /dev/null +++ b/test/compilationTests/zeppelin/ownership/Shareable.sol @@ -0,0 +1,189 @@ +pragma solidity ^0.4.11; + + +/** + * @title Shareable + * @dev inheritable "property" contract that enables methods to be protected by requiring the + * acquiescence of either a single, or, crucially, each of a number of, designated owners. + * @dev Usage: use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by some number (specified in constructor) of the set of owners (specified in the constructor) before the interior is executed. + */ +contract Shareable { + + // struct for the status of a pending operation. + struct PendingState { + uint256 yetNeeded; + uint256 ownersDone; + uint256 index; + } + + // the number of owners that must confirm the same operation before it is run. + uint256 public required; + + // list of owners + address[256] owners; + // index on the list of owners to allow reverse lookup + mapping(address => uint256) ownerIndex; + // the ongoing operations. + mapping(bytes32 => PendingState) pendings; + bytes32[] pendingsIndex; + + + // this contract only has six types of events: it can accept a confirmation, in which case + // we record owner and operation (hash) alongside it. + event Confirmation(address owner, bytes32 operation); + event Revoke(address owner, bytes32 operation); + + + // simple single-sig function modifier. + modifier onlyOwner { + if (!isOwner(msg.sender)) { + throw; + } + _; + } + + /** + * @dev Modifier for multisig functions. + * @param _operation The operation must have an intrinsic hash in order that later attempts can be + * realised as the same underlying operation and thus count as confirmations. + */ + modifier onlymanyowners(bytes32 _operation) { + if (confirmAndCheck(_operation)) { + _; + } + } + + /** + * @dev Constructor is given the number of sigs required to do protected "onlymanyowners" + * transactions as well as the selection of addresses capable of confirming them. + * @param _owners A list of owners. + * @param _required The amount required for a transaction to be approved. + */ + function Shareable(address[] _owners, uint256 _required) { + owners[1] = msg.sender; + ownerIndex[msg.sender] = 1; + for (uint256 i = 0; i < _owners.length; ++i) { + owners[2 + i] = _owners[i]; + ownerIndex[_owners[i]] = 2 + i; + } + required = _required; + if (required > owners.length) { + throw; + } + } + + /** + * @dev Revokes a prior confirmation of the given operation. + * @param _operation A string identifying the operation. + */ + function revoke(bytes32 _operation) external { + uint256 index = ownerIndex[msg.sender]; + // make sure they're an owner + if (index == 0) { + return; + } + uint256 ownerIndexBit = 2**index; + var pending = pendings[_operation]; + if (pending.ownersDone & ownerIndexBit > 0) { + pending.yetNeeded++; + pending.ownersDone -= ownerIndexBit; + Revoke(msg.sender, _operation); + } + } + + /** + * @dev Gets an owner by 0-indexed position (using numOwners as the count) + * @param ownerIndex uint256 The index of the owner + * @return The address of the owner + */ + function getOwner(uint256 ownerIndex) external constant returns (address) { + return address(owners[ownerIndex + 1]); + } + + /** + * @dev Checks if given address is an owner. + * @param _addr address The address which you want to check. + * @return True if the address is an owner and fase otherwise. + */ + function isOwner(address _addr) constant returns (bool) { + return ownerIndex[_addr] > 0; + } + + /** + * @dev Function to check is specific owner has already confirme the operation. + * @param _operation The operation identifier. + * @param _owner The owner address. + * @return True if the owner has confirmed and false otherwise. + */ + function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { + var pending = pendings[_operation]; + uint256 index = ownerIndex[_owner]; + + // make sure they're an owner + if (index == 0) { + return false; + } + + // determine the bit to set for this owner. + uint256 ownerIndexBit = 2**index; + return !(pending.ownersDone & ownerIndexBit == 0); + } + + /** + * @dev Confirm and operation and checks if it's already executable. + * @param _operation The operation identifier. + * @return Returns true when operation can be executed. + */ + function confirmAndCheck(bytes32 _operation) internal returns (bool) { + // determine what index the present sender is: + uint256 index = ownerIndex[msg.sender]; + // make sure they're an owner + if (index == 0) { + throw; + } + + var pending = pendings[_operation]; + // if we're not yet working on this operation, switch over and reset the confirmation status. + if (pending.yetNeeded == 0) { + // reset count of confirmations needed. + pending.yetNeeded = required; + // reset which owners have confirmed (none) - set our bitmap to 0. + pending.ownersDone = 0; + pending.index = pendingsIndex.length++; + pendingsIndex[pending.index] = _operation; + } + // determine the bit to set for this owner. + uint256 ownerIndexBit = 2**index; + // make sure we (the message sender) haven't confirmed this operation previously. + if (pending.ownersDone & ownerIndexBit == 0) { + Confirmation(msg.sender, _operation); + // ok - check if count is enough to go ahead. + if (pending.yetNeeded <= 1) { + // enough confirmations: reset and run interior. + delete pendingsIndex[pendings[_operation].index]; + delete pendings[_operation]; + return true; + } else { + // not enough: record that this owner in particular confirmed. + pending.yetNeeded--; + pending.ownersDone |= ownerIndexBit; + } + } + return false; + } + + + /** + * @dev Clear the pending list. + */ + function clearPending() internal { + uint256 length = pendingsIndex.length; + for (uint256 i = 0; i < length; ++i) { + if (pendingsIndex[i] != 0) { + delete pendings[pendingsIndex[i]]; + } + } + delete pendingsIndex; + } + +} diff --git a/test/compilationTests/zeppelin/payment/PullPayment.sol b/test/compilationTests/zeppelin/payment/PullPayment.sol new file mode 100644 index 00000000..ba710b53 --- /dev/null +++ b/test/compilationTests/zeppelin/payment/PullPayment.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.4.11; + + +import '../math/SafeMath.sol'; + + +/** + * @title PullPayment + * @dev Base contract supporting async send for pull payments. Inherit from this + * contract and use asyncSend instead of send. + */ +contract PullPayment { + using SafeMath for uint256; + + mapping(address => uint256) public payments; + uint256 public totalPayments; + + /** + * @dev Called by the payer to store the sent amount as credit to be pulled. + * @param dest The destination address of the funds. + * @param amount The amount to transfer. + */ + function asyncSend(address dest, uint256 amount) internal { + payments[dest] = payments[dest].add(amount); + totalPayments = totalPayments.add(amount); + } + + /** + * @dev withdraw accumulated balance, called by payee. + */ + function withdrawPayments() { + address payee = msg.sender; + uint256 payment = payments[payee]; + + if (payment == 0) { + throw; + } + + if (this.balance < payment) { + throw; + } + + totalPayments = totalPayments.sub(payment); + payments[payee] = 0; + + if (!payee.send(payment)) { + throw; + } + } +} diff --git a/test/compilationTests/zeppelin/token/BasicToken.sol b/test/compilationTests/zeppelin/token/BasicToken.sol new file mode 100644 index 00000000..5618227a --- /dev/null +++ b/test/compilationTests/zeppelin/token/BasicToken.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.4.11; + + +import './ERC20Basic.sol'; +import '../math/SafeMath.sol'; + + +/** + * @title Basic token + * @dev Basic version of StandardToken, with no allowances. + */ +contract BasicToken is ERC20Basic { + using SafeMath for uint256; + + mapping(address => uint256) balances; + + /** + * @dev transfer token for a specified address + * @param _to The address to transfer to. + * @param _value The amount to be transferred. + */ + function transfer(address _to, uint256 _value) { + balances[msg.sender] = balances[msg.sender].sub(_value); + balances[_to] = balances[_to].add(_value); + Transfer(msg.sender, _to, _value); + } + + /** + * @dev Gets the balance of the specified address. + * @param _owner The address to query the the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address _owner) constant returns (uint256 balance) { + return balances[_owner]; + } + +} diff --git a/test/compilationTests/zeppelin/token/ERC20.sol b/test/compilationTests/zeppelin/token/ERC20.sol new file mode 100644 index 00000000..1045ac35 --- /dev/null +++ b/test/compilationTests/zeppelin/token/ERC20.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.4.11; + + +import './ERC20Basic.sol'; + + +/** + * @title ERC20 interface + * @dev see https://github.com/ethereum/EIPs/issues/20 + */ +contract ERC20 is ERC20Basic { + function allowance(address owner, address spender) constant returns (uint256); + function transferFrom(address from, address to, uint256 value); + function approve(address spender, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); +} diff --git a/test/compilationTests/zeppelin/token/ERC20Basic.sol b/test/compilationTests/zeppelin/token/ERC20Basic.sol new file mode 100644 index 00000000..0e98779e --- /dev/null +++ b/test/compilationTests/zeppelin/token/ERC20Basic.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.4.11; + + +/** + * @title ERC20Basic + * @dev Simpler version of ERC20 interface + * @dev see https://github.com/ethereum/EIPs/issues/20 + */ +contract ERC20Basic { + uint256 public totalSupply; + function balanceOf(address who) constant returns (uint256); + function transfer(address to, uint256 value); + event Transfer(address indexed from, address indexed to, uint256 value); +} diff --git a/test/compilationTests/zeppelin/token/LimitedTransferToken.sol b/test/compilationTests/zeppelin/token/LimitedTransferToken.sol new file mode 100644 index 00000000..ee5032c9 --- /dev/null +++ b/test/compilationTests/zeppelin/token/LimitedTransferToken.sol @@ -0,0 +1,57 @@ +pragma solidity ^0.4.11; + +import "./ERC20.sol"; + +/** + * @title LimitedTransferToken + * @dev 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. + * 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: + * function transferableTokens(address holder, uint64 time) constant public returns (uint256) { + * return min256(unlockedTokens, super.transferableTokens(holder, time)); + * } + * A working example is VestedToken.sol: + * https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/VestedToken.sol + */ + +contract LimitedTransferToken is ERC20 { + + /** + * @dev Checks whether it can transfer or otherwise throws. + */ + modifier canTransfer(address _sender, uint256 _value) { + if (_value > transferableTokens(_sender, uint64(now))) throw; + _; + } + + /** + * @dev Checks modifier and allows transfer if tokens are not locked. + * @param _to The address that will recieve the tokens. + * @param _value The amount of tokens to be transferred. + */ + function transfer(address _to, uint256 _value) canTransfer(msg.sender, _value) { + super.transfer(_to, _value); + } + + /** + * @dev Checks modifier and allows transfer if tokens are not locked. + * @param _from The address that will send the tokens. + * @param _to The address that will recieve the tokens. + * @param _value The amount of tokens to be transferred. + */ + function transferFrom(address _from, address _to, uint256 _value) canTransfer(_from, _value) { + super.transferFrom(_from, _to, _value); + } + + /** + * @dev Default transferable tokens function returns all tokens for a holder (no limit). + * @dev Overwriting transferableTokens(address holder, uint64 time) is the way to provide the + * specific logic for limiting token transferability for a holder over time. + */ + function transferableTokens(address holder, uint64 time) constant public returns (uint256) { + return balanceOf(holder); + } +} diff --git a/test/compilationTests/zeppelin/token/MintableToken.sol b/test/compilationTests/zeppelin/token/MintableToken.sol new file mode 100644 index 00000000..505d13c3 --- /dev/null +++ b/test/compilationTests/zeppelin/token/MintableToken.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.4.11; + + +import './StandardToken.sol'; +import '../ownership/Ownable.sol'; + + + +/** + * @title Mintable token + * @dev Simple ERC20 Token example, with mintable token creation + * @dev 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, uint256 amount); + event MintFinished(); + + bool public mintingFinished = false; + + + modifier canMint() { + if(mintingFinished) throw; + _; + } + + /** + * @dev Function to mint tokens + * @param _to The address that will recieve the minted tokens. + * @param _amount The amount of tokens to mint. + * @return A boolean that indicates if the operation was successful. + */ + function mint(address _to, uint256 _amount) onlyOwner canMint returns (bool) { + totalSupply = totalSupply.add(_amount); + balances[_to] = balances[_to].add(_amount); + Mint(_to, _amount); + return true; + } + + /** + * @dev Function to stop minting new tokens. + * @return True if the operation was successful. + */ + function finishMinting() onlyOwner returns (bool) { + mintingFinished = true; + MintFinished(); + return true; + } +} diff --git a/test/compilationTests/zeppelin/token/PausableToken.sol b/test/compilationTests/zeppelin/token/PausableToken.sol new file mode 100644 index 00000000..8ee114e1 --- /dev/null +++ b/test/compilationTests/zeppelin/token/PausableToken.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.11; + +import './StandardToken.sol'; +import '../lifecycle/Pausable.sol'; + +/** + * Pausable token + * + * Simple ERC20 Token example, with pausable token creation + **/ + +contract PausableToken is StandardToken, Pausable { + + function transfer(address _to, uint _value) whenNotPaused { + super.transfer(_to, _value); + } + + function transferFrom(address _from, address _to, uint _value) whenNotPaused { + super.transferFrom(_from, _to, _value); + } +} diff --git a/test/compilationTests/zeppelin/token/SimpleToken.sol b/test/compilationTests/zeppelin/token/SimpleToken.sol new file mode 100644 index 00000000..898cb21d --- /dev/null +++ b/test/compilationTests/zeppelin/token/SimpleToken.sol @@ -0,0 +1,28 @@ +pragma solidity ^0.4.11; + + +import "./StandardToken.sol"; + + +/** + * @title SimpleToken + * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator. + * Note they can later distribute these tokens as they wish using `transfer` and other + * `StandardToken` functions. + */ +contract SimpleToken is StandardToken { + + string public name = "SimpleToken"; + string public symbol = "SIM"; + uint256 public decimals = 18; + uint256 public INITIAL_SUPPLY = 10000; + + /** + * @dev Contructor that gives msg.sender all of existing tokens. + */ + function SimpleToken() { + totalSupply = INITIAL_SUPPLY; + balances[msg.sender] = INITIAL_SUPPLY; + } + +} diff --git a/test/compilationTests/zeppelin/token/StandardToken.sol b/test/compilationTests/zeppelin/token/StandardToken.sol new file mode 100644 index 00000000..b1b49fe3 --- /dev/null +++ b/test/compilationTests/zeppelin/token/StandardToken.sol @@ -0,0 +1,65 @@ +pragma solidity ^0.4.11; + + +import './BasicToken.sol'; +import './ERC20.sol'; + + +/** + * @title Standard ERC20 token + * + * @dev Implementation of the basic standard token. + * @dev https://github.com/ethereum/EIPs/issues/20 + * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + */ +contract StandardToken is ERC20, BasicToken { + + mapping (address => mapping (address => uint256)) allowed; + + + /** + * @dev Transfer tokens from one address to another + * @param _from address The address which you want to send tokens from + * @param _to address The address which you want to transfer to + * @param _value uint256 the amout of tokens to be transfered + */ + function transferFrom(address _from, address _to, uint256 _value) { + var _allowance = allowed[_from][msg.sender]; + + // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met + // if (_value > _allowance) throw; + + balances[_to] = balances[_to].add(_value); + balances[_from] = balances[_from].sub(_value); + allowed[_from][msg.sender] = _allowance.sub(_value); + Transfer(_from, _to, _value); + } + + /** + * @dev Aprove the passed address to spend the specified amount of tokens on behalf of msg.sender. + * @param _spender The address which will spend the funds. + * @param _value The amount of tokens to be spent. + */ + function approve(address _spender, uint256 _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; + + allowed[msg.sender][_spender] = _value; + Approval(msg.sender, _spender, _value); + } + + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param _owner address The address which owns the funds. + * @param _spender address The address which will spend the funds. + * @return A uint256 specifing the amount of tokens still avaible for the spender. + */ + function allowance(address _owner, address _spender) constant returns (uint256 remaining) { + return allowed[_owner][_spender]; + } + +} diff --git a/test/compilationTests/zeppelin/token/TokenTimelock.sol b/test/compilationTests/zeppelin/token/TokenTimelock.sol new file mode 100644 index 00000000..595bf8d0 --- /dev/null +++ b/test/compilationTests/zeppelin/token/TokenTimelock.sol @@ -0,0 +1,41 @@ +pragma solidity ^0.4.11; + + +import './ERC20Basic.sol'; + +/** + * @title TokenTimelock + * @dev TokenTimelock is a token holder contract that will allow a + * beneficiary to extract the tokens after a given release time + */ +contract TokenTimelock { + + // ERC20 basic token contract being held + ERC20Basic token; + + // beneficiary of tokens after they are released + address beneficiary; + + // timestamp when token release is enabled + uint releaseTime; + + function TokenTimelock(ERC20Basic _token, address _beneficiary, uint _releaseTime) { + require(_releaseTime > now); + token = _token; + beneficiary = _beneficiary; + releaseTime = _releaseTime; + } + + /** + * @dev beneficiary claims tokens held by time lock + */ + function claim() { + require(msg.sender == beneficiary); + require(now >= releaseTime); + + uint amount = token.balanceOf(this); + require(amount > 0); + + token.transfer(beneficiary, amount); + } +} diff --git a/test/compilationTests/zeppelin/token/VestedToken.sol b/test/compilationTests/zeppelin/token/VestedToken.sol new file mode 100644 index 00000000..b7748b09 --- /dev/null +++ b/test/compilationTests/zeppelin/token/VestedToken.sol @@ -0,0 +1,248 @@ +pragma solidity ^0.4.11; + +import "../math/Math.sol"; +import "./StandardToken.sol"; +import "./LimitedTransferToken.sol"; + +/** + * @title Vested token + * @dev Tokens that can be vested for a group of addresses. + */ +contract VestedToken is StandardToken, LimitedTransferToken { + + uint256 MAX_GRANTS_PER_ADDRESS = 20; + + struct TokenGrant { + address granter; // 20 bytes + uint256 value; // 32 bytes + uint64 cliff; + uint64 vesting; + uint64 start; // 3 * 8 = 24 bytes + bool revokable; + bool burnsOnRevoke; // 2 * 1 = 2 bits? or 2 bytes? + } // total 78 bytes = 3 sstore per operation (32 per sstore) + + mapping (address => TokenGrant[]) public grants; + + event NewTokenGrant(address indexed from, address indexed to, uint256 value, uint256 grantId); + + /** + * @dev Grant tokens to a specified address + * @param _to address The address which the tokens will be granted to. + * @param _value uint256 The amount of tokens to be granted. + * @param _start uint64 Time of the beginning of the grant. + * @param _cliff uint64 Time of the cliff period. + * @param _vesting uint64 The vesting period. + */ + function grantVestedTokens( + address _to, + uint256 _value, + uint64 _start, + uint64 _cliff, + uint64 _vesting, + bool _revokable, + bool _burnsOnRevoke + ) public { + + // Check for date inconsistencies that may cause unexpected behavior + if (_cliff < _start || _vesting < _cliff) { + throw; + } + + if (tokenGrantsCount(_to) > MAX_GRANTS_PER_ADDRESS) throw; // To prevent a user being spammed and have his balance locked (out of gas attack when calculating vesting). + + uint256 count = grants[_to].push( + TokenGrant( + _revokable ? msg.sender : 0, // avoid storing an extra 20 bytes when it is non-revokable + _value, + _cliff, + _vesting, + _start, + _revokable, + _burnsOnRevoke + ) + ); + + transfer(_to, _value); + + NewTokenGrant(msg.sender, _to, _value, count - 1); + } + + /** + * @dev Revoke the grant of tokens of a specifed address. + * @param _holder The address which will have its tokens revoked. + * @param _grantId The id of the token grant. + */ + function revokeTokenGrant(address _holder, uint256 _grantId) public { + TokenGrant grant = grants[_holder][_grantId]; + + if (!grant.revokable) { // Check if grant was revokable + throw; + } + + if (grant.granter != msg.sender) { // Only granter can revoke it + throw; + } + + address receiver = grant.burnsOnRevoke ? 0xdead : msg.sender; + + uint256 nonVested = nonVestedTokens(grant, uint64(now)); + + // remove grant from array + delete grants[_holder][_grantId]; + grants[_holder][_grantId] = grants[_holder][grants[_holder].length.sub(1)]; + grants[_holder].length -= 1; + + balances[receiver] = balances[receiver].add(nonVested); + balances[_holder] = balances[_holder].sub(nonVested); + + Transfer(_holder, receiver, nonVested); + } + + + /** + * @dev Calculate the total amount of transferable tokens of a holder at a given time + * @param holder address The address of the holder + * @param time uint64 The specific time. + * @return An uint256 representing a holder's total amount of transferable tokens. + */ + function transferableTokens(address holder, uint64 time) constant public returns (uint256) { + uint256 grantIndex = tokenGrantsCount(holder); + + if (grantIndex == 0) return balanceOf(holder); // shortcut for holder without grants + + // 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 = 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 = 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 Math.min256(vestedTransferable, super.transferableTokens(holder, time)); + } + + /** + * @dev Check the amount of grants that an address has. + * @param _holder The holder of the grants. + * @return A uint256 representing the total amount of grants. + */ + function tokenGrantsCount(address _holder) constant returns (uint256 index) { + return grants[_holder].length; + } + + /** + * @dev Calculate amount of vested tokens at a specifc time. + * @param tokens uint256 The amount of tokens grantted. + * @param time uint64 The time to be checked + * @param start uint64 A time representing the begining of the grant + * @param cliff uint64 The cliff period. + * @param vesting uint64 The vesting period. + * @return An uint256 representing the amount of vested tokensof a specif grant. + * transferableTokens + * | _/-------- vestedTokens rect + * | _/ + * | _/ + * | _/ + * | _/ + * | / + * | .| + * | . | + * | . | + * | . | + * | . | + * | . | + * +===+===========+---------+----------> time + * Start Clift Vesting + */ + function calculateVestedTokens( + uint256 tokens, + uint256 time, + uint256 start, + uint256 cliff, + uint256 vesting) constant returns (uint256) + { + // Shortcuts for before cliff and after vesting cases. + if (time < cliff) return 0; + if (time >= vesting) return tokens; + + // Interpolate all vested tokens. + // As before cliff the shortcut returns 0, we can use just calculate a value + // in the vesting rect (as shown in above's figure) + + // vestedTokens = tokens * (time - start) / (vesting - start) + uint256 vestedTokens = SafeMath.div( + SafeMath.mul( + tokens, + SafeMath.sub(time, start) + ), + SafeMath.sub(vesting, start) + ); + + return vestedTokens; + } + + /** + * @dev Get all information about a specifc grant. + * @param _holder The address which will have its tokens revoked. + * @param _grantId The id of the token grant. + * @return Returns all the values that represent a TokenGrant(address, value, start, cliff, + * revokability, burnsOnRevoke, and vesting) plus the vested value at the current time. + */ + function tokenGrant(address _holder, uint256 _grantId) constant returns (address granter, uint256 value, uint256 vested, uint64 start, uint64 cliff, uint64 vesting, bool revokable, bool burnsOnRevoke) { + TokenGrant grant = grants[_holder][_grantId]; + + granter = grant.granter; + value = grant.value; + start = grant.start; + cliff = grant.cliff; + vesting = grant.vesting; + revokable = grant.revokable; + burnsOnRevoke = grant.burnsOnRevoke; + + vested = vestedTokens(grant, uint64(now)); + } + + /** + * @dev Get the amount of vested tokens at a specific time. + * @param grant TokenGrant The grant to be checked. + * @param time The time to be checked + * @return An uint256 representing the amount of vested tokens of a specific grant at a specific time. + */ + function vestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) { + return calculateVestedTokens( + grant.value, + uint256(time), + uint256(grant.start), + uint256(grant.cliff), + uint256(grant.vesting) + ); + } + + /** + * @dev Calculate the amount of non vested tokens at a specific time. + * @param grant TokenGrant The grant to be checked. + * @param time uint64 The time to be checked + * @return An uint256 representing the amount of non vested tokens of a specifc grant on the + * passed time frame. + */ + function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) { + return grant.value.sub(vestedTokens(grant, time)); + } + + /** + * @dev Calculate the date when the holder can trasfer all its tokens + * @param holder address The address of the holder + * @return An uint256 representing the date of the last transferable tokens. + */ + 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 = Math.max64(grants[holder][i].vesting, date); + } + } +} -- cgit