updated the crowdsale contract doc

updated the crowdsale contract doc

pragma solidity ^0.4.10;
import './Owned.sol';
import './SafeMath.sol';
import './TokenChangerInterface.sol';
import './SmartTokenInterface.sol';

/*
    Open issues:
    - all values are placeholders, need to update them with real values
    - verify ERC20 token addresses, transferFrom (must return a boolean flag) and update them with the correct values
    - possibly move all the ERC20 token initialization from the initERC20Tokens function to a different contract to lower the gas cost and make the crowdsale changer more generic
    - possibly add getters for ERC20 token fields so that the client won't need to rely on the order in the struct
*/

// interfaces

contract EtherToken {
    function deposit() public payable;
    function transfer(address _to, uint256 _value) public returns (bool success);
}

/*
    Crowdsale Changer v0.1

    The crowdsale version of the token changer, allows buying the smart token with ether/other ERC20 tokens

    Note that during the crowdsale, the price remains fixed by keeping the same ratio between the reserve and the supply.
*/
contract CrowdsaleChanger is Owned, SafeMath, TokenChangerInterface {
    struct ERC20TokenData {
        uint256 valueN;     // 1 smallest unit in wei (numerator)
        uint256 valueD;     // 1 smallest unit in wei (denominator)
        uint16 limit;       // maximum contribution in percentage out of the total ETH raised so far. 1-1000 (10 == 1%), divided by 1000, 0 to disable
        bool isEnabled;     // is purchase of the smart token enabled with the ERC20 token, can be set by the owner
        bool isSet;         // used to tell if the mapping element is defined
    }

    uint256 public constant DURATION = 30 days;                     // crowdsale duration
    uint256 public constant ETHER_CAP = 1000000 ether;              // maximum ether contribution
    uint256 public constant BITCOIN_SUISSE_ETHER_CAP = 20000 ether; // maximum bitcoin suisse ether contribution
    uint256 public constant INITIAL_PRICE_N = 1;                    // initial price in wei (numerator)
    uint256 public constant INITIAL_PRICE_D = 100;                  // initial price in wei (denominator)
    uint8 public constant RESERVE_RATIO = 21;                       // constant reserve ratio for the new token, used to calculate the current price
    uint8 public constant BENEFICIARY_PERCENTAGE = 30;              // percentage out of the total supply that should be issued to the beneficiary

    // phases
    uint256 public constant PHASE1_MIN_CONTRIBUTION = 0 ether;
    uint256 public constant PHASE2_MIN_CONTRIBUTION = 100000 ether;
    uint256 public constant PHASE3_MIN_CONTRIBUTION = 300000 ether;
    // % of contribution allocated to the reserve
    uint8 public constant PHASE1_RESERVE_ALLOCATION = 30;
    uint8 public constant PHASE2_RESERVE_ALLOCATION = 50;
    uint8 public constant PHASE3_RESERVE_ALLOCATION = 70;

    string public version = '0.1';
    string public changerType = 'crowdsale';

    uint256 public startTime = 0;                               // crowdsale start time (in seconds)
    uint256 public endTime = 0;                                 // crowdsale end time (in seconds)
    uint256 public totalEtherContributed = 0;                   // ether contributed so far
    uint256 public tokenReserveBalance = 0;                     // amount of the ether contributed so far that gets into the smart token's reserve, used to calculate the current price
    address public etherToken = 0x0;                            // ether token contract address
    address public beneficiary = 0x0;                           // address to receive all contributed ether
    address public bitcoinSuisse = 0x0;                         // bitcoin suisse address
    SmartTokenInterface public token;                           // smart token governed by the changer
    address[] public acceptedTokens;                            // ERC20 standard token addresses
    mapping (address => ERC20TokenData) public tokenData;       // ERC20 token addresses -> ERC20 token data
    mapping (address => uint256) public beneficiaryBalances;    // beneficiary balances in the different tokens

    // triggered when a change between two tokens occurs
    event Change(address indexed _fromToken, address indexed _toToken, address indexed _trader, uint256 _amount, uint256 _return);

    /*
        _token          smart token governed by the changer
        _etherToken     ether token contract address
        _startTime      crowdsale start time
        _beneficiary    address to receive all contributed ether
        _bitcoinSuisse  bitcoin suisse address
    */
    function CrowdsaleChanger(address _token, address _etherToken, uint256 _startTime, address _beneficiary, address _bitcoinSuisse)
        validAddress(_token)
        validAddress(_etherToken)
        validAddress(_beneficiary)
        validAddress(_bitcoinSuisse)
        earlierThan(_startTime)
    {
        token = SmartTokenInterface(_token);
        etherToken = _etherToken;
        startTime = _startTime;
        endTime = startTime + DURATION;
        beneficiary = _beneficiary;
        bitcoinSuisse = _bitcoinSuisse;

        addERC20Token(_etherToken, 0, 1, 1); // Ether
    }

    // validates an address - currently only checks that it isn't null
    modifier validAddress(address _address) {
        require(_address != 0x0);
        _;
    }

    // validates an ERC20 token address - verifies that the address belongs to one of the ERC20 tokens
    modifier validERC20Token(address _address) {
        require(tokenData[_address].isSet);
        _;
    }

    // validates a token address - verifies that the address belongs to one of the changeable tokens
    modifier validToken(address _address) {
        require(_address == address(token) || tokenData[_address].isSet);
        _;
    }

    // validates ERC20 token limit
    modifier validERC20TokenLimit(uint16 _limit) {
        require(_limit <= 1000);
        _;
    }

    // ensures that token changing is connected to the smart token
    modifier active() {
        assert(token.changer() == address(this));
        _;
    }

    // ensures that token changing is not conneccted to the smart token
    modifier inactive() {
        assert(token.changer() != address(this));
        _;
    }

    // ensures that it's earlier than the given time
    modifier earlierThan(uint256 _time) {
        assert(now < _time);
        _;
    }

    // ensures that it's later than the given time
    modifier laterThan(uint256 _time) {
        assert(now > _time);
        _;
    }

    // ensures that we didn't reach the ether cap
    modifier etherCapNotReached() {
        assert(totalEtherContributed < ETHER_CAP);
        _;
    }

    // ensures that the sender is bitcoin suisse
    modifier bitcoinSuisseOnly() {
        assert(msg.sender == bitcoinSuisse);
        _;
    }

    // ensures that we didn't reach the bitcoin suisse ether cap
    modifier bitcoinSuisseEtherCapNotReached(uint256 _ethContribution) {
        require(safeAdd(totalEtherContributed, _ethContribution) <= BITCOIN_SUISSE_ETHER_CAP);
        _;
    }

    /*
        returns the number of changeable tokens supported by the contract
        note that the number of changeable tokens is the number of ERC20 tokens plus the smart token
    */
    function changeableTokenCount() public constant returns (uint16 count) {
        return uint16(acceptedTokens.length + 1);
    }

    /*
        given a changeable token index, returns the changeable token contract address
    */
    function changeableToken(uint16 _tokenIndex) public constant returns (address tokenAddress) {
        if (_tokenIndex == 0)
            return token;
        return acceptedTokens[_tokenIndex - 1];
    }

    function initERC20Tokens()
        public
        ownerOnly
        inactive
    {
        addERC20Token(0xa74476443119A942dE498590Fe1f2454d7D4aC0d, 20, 1, 1); // Golem
        addERC20Token(0x48c80F1f4D53D5951e5D5438B54Cba84f29F32a5, 20, 1, 1); // Augur

        addERC20Token(0x6810e776880C02933D47DB1b9fc05908e5386b96, 10, 1, 1); // Gnosis
        addERC20Token(0xaeC2E87E0A235266D9C5ADc9DEb4b2E29b54D009, 10, 1, 1); // SingularDTV
        addERC20Token(0xE0B7927c4aF23765Cb51314A0E0521A9645F0E2A, 10, 1, 1); // DigixDAO

        addERC20Token(0x4993CB95c7443bdC06155c5f5688Be9D8f6999a5, 5, 1, 1); // ROUND
        addERC20Token(0x607F4C5BB672230e8672085532f7e901544a7375, 5, 1, 1); // iEx.ec
        addERC20Token(0x888666CA69E0f178DED6D75b5726Cee99A87D698, 5, 1, 1); // ICONOMI
        addERC20Token(0xAf30D2a7E90d7DC361c8C4585e9BB7D2F6f15bc7, 5, 1, 1); // FirstBlood
        addERC20Token(0xBEB9eF514a379B997e0798FDcC901Ee474B6D9A1, 5, 1, 1); // Melon
        addERC20Token(0x667088b212ce3d06a1b553a7221E1fD19000d9aF, 5, 1, 1); // Wings
    }

    /*
        defines a new ERC20 token
        can only be called by the changer owner while the changer is inactive

        _token      address of the ERC20 token
        _limit      maximum contribution in percentage out of the total ETH raised so far. 1-1000 (10 == 1%), divided by 1000
        _valueN     1 smallest unit in wei (numerator)
        _valueD     1 smallest unit in wei (denominator)
    */
    function addERC20Token(address _token, uint16 _limit, uint256 _valueN, uint256 _valueD)
        public
        ownerOnly
        inactive
        validAddress(_token)
        validERC20TokenLimit(_limit)
    {
        require(_token != address(this) && _token != address(token) && !tokenData[_token].isSet && _valueN != 0 && _valueD != 0); // validate input

        tokenData[_token].limit = _limit;
        tokenData[_token].valueN = _valueN;
        tokenData[_token].valueD = _valueD;
        tokenData[_token].isEnabled = true;
        tokenData[_token].isSet = true;
        acceptedTokens.push(_token);
    }

    /*
        updates one of the ERC20 tokens
        can only be called by the changer owner
        note that the function can be called during the crowdsale as well, mainly to update the ERC20 token ETH value

        _erc20Token     address of the ERC20 token
        _limit          maximum contribution in percentage out of the total ETH raised so far. 1-1000 (10 == 1%), divided by 1000
        _valueN         1 smallest unit in wei (numerator)
        _valueD         1 smallest unit in wei (denominator)
    */
    function updateERC20Token(address _erc20Token, uint16 _limit, uint256 _valueN, uint256 _valueD)
        public
        ownerOnly
        validERC20Token(_erc20Token)
        validERC20TokenLimit(_limit)
    {
        require(_valueN != 0 && _valueD != 0); // validate input
        ERC20TokenData data = tokenData[_erc20Token];
        data.limit = _limit;
        data.valueN = _valueN;
        data.valueD = _valueD;
    }

    /*
        disables purchasing with the given ERC20 token in case the token got compromised
        can only be called by the changer owner

        _erc20Token     ERC20 token contract address
        _disable        true to disable the token, false to re-enable it
    */
    function disableERC20Token(address _erc20Token, bool _disable)
        public
        ownerOnly
        validERC20Token(_erc20Token)
    {
        tokenData[_erc20Token].isEnabled = !_disable;
    }

    /*
        withdraws tokens from one of the ERC20 tokens and sends them to an account
        can only be called by the changer owner
        this is a safety mechanism that allows the owner to return tokens that were sent directly to this contract by mistake

        _erc20Token     ERC20 token contract address
        _to             account to receive the new amount
        _amount         amount to withdraw (in the ERC20 token)
    */
    function withdraw(address _erc20Token, address _to, uint256 _amount)
        public
        ownerOnly
        validERC20Token(_erc20Token)
        validAddress(_to)
    {
        require(_to != address(this) && _to != address(token) && _amount != 0); // validate input

        ERC20TokenInterface erc20Token = ERC20TokenInterface(_erc20Token);
        assert(erc20Token.transfer(_to, _amount));
    }

    /*
        sets the smart token's changer address to a different one instead of the current contract address
        can only be called by the owner
        the changer can be set to null to transfer ownership from the changer to the original smart token's owner

        _changer    new changer contract address (can also be set to 0x0 to remove the current changer)
    */
    function setTokenChanger(address _changer) public ownerOnly {
        require(_changer != address(this) && _changer != address(token)); // validate input
        token.setChanger(_changer);
    }

    /*
        returns the expected return for changing a specific amount of _fromToken to _toToken

        _fromToken  token to change from
        _toToken    token to change to
        _amount     amount to change, in fromToken
    */
    function getReturn(address _fromToken, address _toToken, uint256 _amount) public constant returns (uint256 amount) {
        require(_toToken == address(token)); // validate input
        return getPurchaseReturn(_fromToken, _amount);
    }

    /*
        returns the expected return for buying the token for an ERC20 token

        _erc20Token     ERC20 token contract address
        _depositAmount  amount to deposit (in the ERC20 token)
    */
    function getPurchaseReturn(address _erc20Token, uint256 _depositAmount)
        public
        constant
        active
        etherCapNotReached
        validERC20Token(_erc20Token)
        returns (uint256 amount)
    {
        ERC20TokenData data = tokenData[_erc20Token];
        require(data.isEnabled && _depositAmount != 0); // validate input

        uint256 depositEthValue = safeMul(_depositAmount, data.valueN) / data.valueD;
        if (depositEthValue == 0)
            return 0;

        // check ether cap
        require(safeAdd(totalEtherContributed, depositEthValue) <= ETHER_CAP);

        // check limit
        if (data.limit != 0) {
            uint256 balance = beneficiaryBalances[_erc20Token];
            uint256 balanceEthValue = safeMul(balance, data.valueN) / data.valueD;  // ether value of the ERC20 token beneficiary balance
            uint256 limit = safeMul(totalEtherContributed, data.limit) / 1000; // current limit of the ERC20 token
            require(safeAdd(balanceEthValue, depositEthValue) <= limit);
        }

        // first contribution can't use the simplified bancor formula, so using the predefined initial price instead
        if (tokenReserveBalance == 0 || token.totalSupply() == 0)
            return safeMul(depositEthValue, INITIAL_PRICE_D) / INITIAL_PRICE_N;

        // using the simplified bancor formula -
        // Price = Reserve / (Supply * CRR)
        uint256 temp = safeMul(depositEthValue, token.totalSupply());
        temp = safeMul(temp, RESERVE_RATIO);
        return temp / 100 / tokenReserveBalance;
    }

    /*
        changes a specific amount of _fromToken to _toToken

        _fromToken  token to change from
        _toToken    token to change to
        _amount     amount to change, in fromToken
        _minReturn  if the change results in an amount smaller than the minimum return, it is cancelled
    */
    function change(address _fromToken, address _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256 amount) {
        require(_toToken == address(token)); // validate input
        return buyERC20(_fromToken, _amount, _minReturn);
    }

    /*
        buys the token with one of the ERC20 tokens
        requires the called to approve and allowance for the crowdsale contract

        _erc20Token     ERC20 token contract address
        _depositAmount  amount to deposit (in the ERC20 token)
        _minReturn      if the change results in an amount smaller than the minimum return, it is cancelled
    */
    function buyERC20(address _erc20Token, uint256 _depositAmount, uint256 _minReturn)
        public
        laterThan(startTime)
        earlierThan(endTime)
        returns (uint256 amount)
    {
        amount = getPurchaseReturn(_erc20Token, _depositAmount);
        assert(amount != 0 && amount >= _minReturn); // ensure the trade gives something in return and meets the minimum requested amount

        ERC20TokenInterface erc20Token = ERC20TokenInterface(_erc20Token);
        assert(erc20Token.transferFrom(msg.sender, beneficiary, _depositAmount)); // transfer _depositAmount funds from the caller in the ERC20 token
        beneficiaryBalances[erc20Token] = safeAdd(beneficiaryBalances[erc20Token], _depositAmount); // increase beneficiary ERC20 balance

        ERC20TokenData data = tokenData[_erc20Token];
        uint256 depositEthValue = safeMul(_depositAmount, data.valueN) / data.valueD;
        handleContribution(msg.sender, depositEthValue, amount);
        Change(_erc20Token, token, msg.sender, _depositAmount, amount);
        return amount;
    }

    /*
        buys the token with ETH
    */
    function buyETH()
        public
        payable
        laterThan(startTime)
        earlierThan(endTime)
        returns (uint256 amount)
    {
        amount = handleETHDeposit(msg.sender, msg.value);
        Change(etherToken, token, msg.sender, msg.value, amount);
        return amount;
    }

    /*
        buys the token with BTCs (Bitcoin Suisse only)
        can only be called before the crowdsale started

        _contributor    account that should receive the new tokens
    */
    function buyBitcoinSuisse(address _contributor)
        public
        payable
        bitcoinSuisseOnly
        bitcoinSuisseEtherCapNotReached(msg.value)
        earlierThan(startTime)
        returns (uint256 amount)
    {
        amount = handleETHDeposit(_contributor, msg.value);
        Change(etherToken, token, msg.sender, msg.value, amount);
        return amount;
    }

    /*
        handles direct ETH deposits (as opposed to ERC20 contributions)

        _contributor    account that should receive the new tokens
        _depositAmount  amount contributed by the account, in wei
    */
    function handleETHDeposit(address _contributor, uint256 _depositAmount) private returns (uint256 amount) {
        require(_depositAmount > 0); // validate input
        amount = getPurchaseReturn(etherToken, _depositAmount);
        assert(amount != 0); // ensure the trade gives something in return

        EtherToken ethToken = EtherToken(etherToken);
        ethToken.deposit.value(_depositAmount)(); // transfer the ether to the ether contract
        assert(ethToken.transfer(beneficiary, _depositAmount)); // transfer the ether to the beneficiary account
        beneficiaryBalances[etherToken] = safeAdd(beneficiaryBalances[etherToken], _depositAmount); // increase beneficiary ETH balance
        handleContribution(_contributor, _depositAmount, amount);
        return amount;
    }

    /*
        handles the generic part of the contribution - regardless of the type of contribution
        assumes that the contribution was already added to the beneficiary account in the different tokens
        updates the reserve balance, total contributed amount and issues new tokens to the contributor and to the beneficiary

        _contributor        account that should the new tokens
        _depositEthValue    amount contributed by the account, in wei
        _return             amount to be issued to the contributor, in the smart token
    */
    function handleContribution(address _contributor, uint256 _depositEthValue, uint256 _return) private {
        // update the reserve balance
        uint8 reserveAllocationPercentage;
        if (totalEtherContributed >= PHASE3_MIN_CONTRIBUTION)
            reserveAllocationPercentage = PHASE3_RESERVE_ALLOCATION;
        else if (totalEtherContributed >= PHASE2_MIN_CONTRIBUTION)
            reserveAllocationPercentage = PHASE2_RESERVE_ALLOCATION;
        else if (totalEtherContributed >= PHASE1_MIN_CONTRIBUTION)
            reserveAllocationPercentage = PHASE1_RESERVE_ALLOCATION;

        uint256 addToReserve = safeMul(_depositEthValue, reserveAllocationPercentage) / 100;
        tokenReserveBalance = safeAdd(tokenReserveBalance, addToReserve);

        // update the total contribution amount
        totalEtherContributed = safeAdd(totalEtherContributed, _depositEthValue);
        // issue new funds to the contributor in the smart token
        token.issue(_contributor, _return);

        // issue tokens to the beneficiary
        uint256 amount = safeMul(100, _return) / (100 - BENEFICIARY_PERCENTAGE);
        amount = safeSub(amount, _return);
        if (amount == 0)
            return;

        token.issue(beneficiary, amount);
    }

    // fallback
    function() payable {
        buyETH();
    }
}

pragma solidity ^0.4.10;
import './Owned.sol';
import './SafeMath.sol';
import './TokenChangerInterface.sol';
import './SmartTokenInterface.sol';

/*
    Open issues:
    - all values are placeholders, need to update them with real values
    - verify ERC20 token addresses, transferFrom (must return a boolean flag) and update them with the correct values
    - possibly move all the ERC20 token initialization from the initERC20Tokens function to a different contract to lower the gas cost and make the crowdsale changer more generic
    - possibly add getters for ERC20 token fields so that the client won't need to rely on the order in the struct
*/

// interfaces

contract EtherToken {
    function deposit() public payable;
    function transfer(address _to, uint256 _value) public returns (bool success);
}

/*
    Crowdsale Changer v0.1

    The crowdsale version of the token changer, allows buying the smart token with ether/other ERC20 tokens
*/
contract CrowdsaleChanger is Owned, SafeMath, TokenChangerInterface {
    struct ERC20TokenData {
        uint256 valueN;     // 1 smallest unit in wei (numerator)
        uint256 valueD;     // 1 smallest unit in wei (denominator)
        uint16 limit;       // maximum contribution in percentage out of the total ETH raised so far. 1-1000 (10 == 1%), divided by 1000, 0 to disable
        bool isEnabled;     // is purchase of the smart token enabled with the ERC20 token, can be set by the owner
        bool isSet;         // used to tell if the mapping element is defined
    }

    uint256 public constant DURATION = 30 days;                     // crowdsale duration
    uint256 public constant ETHER_CAP = 1000000 ether;              // maximum ether contribution
    uint256 public constant BITCOIN_SUISSE_ETHER_CAP = 20000 ether; // maximum bitcoin suisse ether contribution
    uint256 public constant INITIAL_PRICE_N = 1;                    // initial price in wei (numerator)
    uint256 public constant INITIAL_PRICE_D = 100;                  // initial price in wei (denominator)
    uint8 public constant RESERVE_RATIO = 21;                       // constant reserve ratio for the new token, used to calculate the current price
    uint8 public constant BENEFICIARY_PERCENTAGE = 30;              // percentage out of the total supply that should be issued to the beneficiary

    // phases
    uint256 public constant PHASE1_MIN_CONTRIBUTION = 0 ether;
    uint256 public constant PHASE2_MIN_CONTRIBUTION = 100000 ether;
    uint256 public constant PHASE3_MIN_CONTRIBUTION = 300000 ether;
    // % of contribution allocated to the reserve
    uint8 public constant PHASE1_RESERVE_ALLOCATION = 30;
    uint8 public constant PHASE2_RESERVE_ALLOCATION = 50;
    uint8 public constant PHASE3_RESERVE_ALLOCATION = 70;

    string public version = '0.1';
    string public changerType = 'crowdsale';

    uint256 public startTime = 0;                               // crowdsale start time (in seconds)
    uint256 public endTime = 0;                                 // crowdsale end time (in seconds)
    uint256 public totalEtherContributed = 0;                   // ether contributed so far
    uint256 public tokenReserveBalance = 0;                     // amount of the ether contributed so far that gets into the smart token's reserve, used to calculate the current price
    address public etherToken = 0x0;                            // ether token contract address
    address public beneficiary = 0x0;                           // address to receive all contributed ether
    address public bitcoinSuisse = 0x0;                         // bitcoin suisse address
    SmartTokenInterface public token;                           // smart token governed by the changer
    address[] public acceptedTokens;                            // ERC20 standard token addresses
    mapping (address => ERC20TokenData) public tokenData;       // ERC20 token addresses -> ERC20 token data
    mapping (address => uint256) public beneficiaryBalances;    // beneficiary balances in the different tokens

    // triggered when a change between two tokens occurs
    event Change(address indexed _fromToken, address indexed _toToken, address indexed _trader, uint256 _amount, uint256 _return);

    /*
        _token          smart token governed by the changer
        _etherToken     ether token contract address
        _startTime      crowdsale start time
        _beneficiary    address to receive all contributed ether
        _bitcoinSuisse  bitcoin suisse address
    */
    function CrowdsaleChanger(address _token, address _etherToken, uint256 _startTime, address _beneficiary, address _bitcoinSuisse)
        validAddress(_token)
        validAddress(_etherToken)
        validAddress(_beneficiary)
        validAddress(_bitcoinSuisse)
        earlierThan(_startTime)
    {
        token = SmartTokenInterface(_token);
        etherToken = _etherToken;
        startTime = _startTime;
        endTime = startTime + DURATION;
        beneficiary = _beneficiary;
        bitcoinSuisse = _bitcoinSuisse;

        addERC20Token(_etherToken, 0, 1, 1); // Ether
    }

    // validates an address - currently only checks that it isn't null
    modifier validAddress(address _address) {
        require(_address != 0x0);
        _;
    }

    // validates an ERC20 token address - verifies that the address belongs to one of the ERC20 tokens
    modifier validERC20Token(address _address) {
        require(tokenData[_address].isSet);
        _;
    }

    // validates a token address - verifies that the address belongs to one of the changeable tokens
    modifier validToken(address _address) {
        require(_address == address(token) || tokenData[_address].isSet);
        _;
    }

    // validates ERC20 token limit
    modifier validERC20TokenLimit(uint16 _limit) {
        require(_limit <= 1000);
        _;
    }

    // ensures that token changing is connected to the smart token
    modifier active() {
        assert(token.changer() == address(this));
        _;
    }

    // ensures that token changing is not conneccted to the smart token
    modifier inactive() {
        assert(token.changer() != address(this));
        _;
    }

    // ensures that it's earlier than the given time
    modifier earlierThan(uint256 _time) {
        assert(now < _time);
        _;
    }

    // ensures that it's later than the given time
    modifier laterThan(uint256 _time) {
        assert(now > _time);
        _;
    }

    // ensures that we didn't reach the ether cap
    modifier etherCapNotReached() {
        assert(totalEtherContributed < ETHER_CAP);
        _;
    }

    // ensures that the sender is bitcoin suisse
    modifier bitcoinSuisseOnly() {
        assert(msg.sender == bitcoinSuisse);
        _;
    }

    // ensures that we didn't reach the bitcoin suisse ether cap
    modifier bitcoinSuisseEtherCapNotReached(uint256 _ethContribution) {
        require(safeAdd(totalEtherContributed, _ethContribution) <= BITCOIN_SUISSE_ETHER_CAP);
        _;
    }

    /*
        returns the number of changeable tokens supported by the contract
        note that the number of changeable tokens is the number of ERC20 tokens plus the smart token
    */
    function changeableTokenCount() public constant returns (uint16 count) {
        return uint16(acceptedTokens.length + 1);
    }

    /*
        given a changeable token index, returns the changeable token contract address
    */
    function changeableToken(uint16 _tokenIndex) public constant returns (address tokenAddress) {
        if (_tokenIndex == 0)
            return token;
        return acceptedTokens[_tokenIndex - 1];
    }

    function initERC20Tokens()
        public
        ownerOnly
        inactive
    {
        addERC20Token(0xa74476443119A942dE498590Fe1f2454d7D4aC0d, 20, 1, 1); // Golem
        addERC20Token(0x48c80F1f4D53D5951e5D5438B54Cba84f29F32a5, 20, 1, 1); // Augur

        addERC20Token(0x6810e776880C02933D47DB1b9fc05908e5386b96, 10, 1, 1); // Gnosis
        addERC20Token(0xaeC2E87E0A235266D9C5ADc9DEb4b2E29b54D009, 10, 1, 1); // SingularDTV
        addERC20Token(0xE0B7927c4aF23765Cb51314A0E0521A9645F0E2A, 10, 1, 1); // DigixDAO

        addERC20Token(0x4993CB95c7443bdC06155c5f5688Be9D8f6999a5, 5, 1, 1); // ROUND
        addERC20Token(0x607F4C5BB672230e8672085532f7e901544a7375, 5, 1, 1); // iEx.ec
        addERC20Token(0x888666CA69E0f178DED6D75b5726Cee99A87D698, 5, 1, 1); // ICONOMI
        addERC20Token(0xAf30D2a7E90d7DC361c8C4585e9BB7D2F6f15bc7, 5, 1, 1); // FirstBlood
        addERC20Token(0xBEB9eF514a379B997e0798FDcC901Ee474B6D9A1, 5, 1, 1); // Melon
        addERC20Token(0x667088b212ce3d06a1b553a7221E1fD19000d9aF, 5, 1, 1); // Wings
    }

    /*
        defines a new ERC20 token
        can only be called by the changer owner while the changer is inactive

        _token      address of the ERC20 token
        _limit      maximum contribution in percentage out of the total ETH raised so far. 1-1000 (10 == 1%), divided by 1000
        _valueN     1 smallest unit in wei (numerator)
        _valueD     1 smallest unit in wei (denominator)
    */
    function addERC20Token(address _token, uint16 _limit, uint256 _valueN, uint256 _valueD)
        public
        ownerOnly
        inactive
        validAddress(_token)
        validERC20TokenLimit(_limit)
    {
        require(_token != address(this) && _token != address(token) && !tokenData[_token].isSet && _valueN != 0 && _valueD != 0); // validate input

        tokenData[_token].limit = _limit;
        tokenData[_token].valueN = _valueN;
        tokenData[_token].valueD = _valueD;
        tokenData[_token].isEnabled = true;
        tokenData[_token].isSet = true;
        acceptedTokens.push(_token);
    }

    /*
        updates one of the ERC20 tokens
        can only be called by the changer owner
        note that the function can be called during the crowdsale as well, mainly to update the ERC20 token ETH value

        _erc20Token     address of the ERC20 token
        _limit          maximum contribution in percentage out of the total ETH raised so far. 1-1000 (10 == 1%), divided by 1000
        _valueN         1 smallest unit in wei (numerator)
        _valueD         1 smallest unit in wei (denominator)
    */
    function updateERC20Token(address _erc20Token, uint16 _limit, uint256 _valueN, uint256 _valueD)
        public
        ownerOnly
        validERC20Token(_erc20Token)
        validERC20TokenLimit(_limit)
    {
        require(_valueN != 0 && _valueD != 0); // validate input
        ERC20TokenData data = tokenData[_erc20Token];
        data.limit = _limit;
        data.valueN = _valueN;
        data.valueD = _valueD;
    }

    /*
        disables purchasing with the given ERC20 token in case the token got compromised
        can only be called by the changer owner

        _erc20Token     ERC20 token contract address
        _disable        true to disable the token, false to re-enable it
    */
    function disableERC20Token(address _erc20Token, bool _disable)
        public
        ownerOnly
        validERC20Token(_erc20Token)
    {
        tokenData[_erc20Token].isEnabled = !_disable;
    }

    /*
        withdraws tokens from one of the ERC20 tokens and sends them to an account
        can only be called by the changer owner
        this is a safety mechanism that allows the owner to return tokens that were sent directly to this contract by mistake

        _erc20Token     ERC20 token contract address
        _to             account to receive the new amount
        _amount         amount to withdraw (in the ERC20 token)
    */
    function withdraw(address _erc20Token, address _to, uint256 _amount)
        public
        ownerOnly
        validERC20Token(_erc20Token)
        validAddress(_to)
    {
        require(_to != address(this) && _to != address(token) && _amount != 0); // validate input

        ERC20TokenInterface erc20Token = ERC20TokenInterface(_erc20Token);
        assert(erc20Token.transfer(_to, _amount));
    }

    /*
        sets the smart token's changer address to a different one instead of the current contract address
        can only be called by the owner
        the changer can be set to null to transfer ownership from the changer to the original smart token's owner

        _changer    new changer contract address (can also be set to 0x0 to remove the current changer)
    */
    function setTokenChanger(address _changer) public ownerOnly {
        require(_changer != address(this) && _changer != address(token)); // validate input
        token.setChanger(_changer);
    }

    /*
        returns the expected return for changing a specific amount of _fromToken to _toToken

        _fromToken  token to change from
        _toToken    token to change to
        _amount     amount to change, in fromToken
    */
    function getReturn(address _fromToken, address _toToken, uint256 _amount) public constant returns (uint256 amount) {
        require(_toToken == address(token)); // validate input
        return getPurchaseReturn(_fromToken, _amount);
    }

    /*
        returns the expected return for buying the token for an ERC20 token

        _erc20Token     ERC20 token contract address
        _depositAmount  amount to deposit (in the ERC20 token)
    */
    function getPurchaseReturn(address _erc20Token, uint256 _depositAmount)
        public
        constant
        active
        etherCapNotReached
        validERC20Token(_erc20Token)
        returns (uint256 amount)
    {
        ERC20TokenData data = tokenData[_erc20Token];
        require(data.isEnabled && _depositAmount != 0); // validate input

        uint256 depositEthValue = safeMul(_depositAmount, data.valueN) / data.valueD;
        if (depositEthValue == 0)
            return 0;

        // check ether cap
        require(safeAdd(totalEtherContributed, depositEthValue) <= ETHER_CAP);

        // check limit
        if (data.limit != 0) {
            uint256 balance = beneficiaryBalances[_erc20Token];
            uint256 balanceEthValue = safeMul(balance, data.valueN) / data.valueD;  // ether value of the ERC20 token beneficiary balance
            uint256 limit = safeMul(totalEtherContributed, data.limit) / 1000; // current limit of the ERC20 token
            require(safeAdd(balanceEthValue, depositEthValue) <= limit);
        }

        // first contribution can't use the simplified bancor formula, so using the predefined initial price instead
        if (tokenReserveBalance == 0 || token.totalSupply() == 0)
            return safeMul(depositEthValue, INITIAL_PRICE_D) / INITIAL_PRICE_N;

        // using the simplified bancor formula -
        // Price = Reserve / (Supply * CRR)
        uint256 temp = safeMul(depositEthValue, token.totalSupply());
        temp = safeMul(temp, RESERVE_RATIO);
        return temp / 100 / tokenReserveBalance;
    }

    /*
        changes a specific amount of _fromToken to _toToken

        _fromToken  token to change from
        _toToken    token to change to
        _amount     amount to change, in fromToken
        _minReturn  if the change results in an amount smaller than the minimum return, it is cancelled
    */
    function change(address _fromToken, address _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256 amount) {
        require(_toToken == address(token)); // validate input
        return buyERC20(_fromToken, _amount, _minReturn);
    }

    /*
        buys the token with one of the ERC20 tokens
        requires the called to approve and allowance for the crowdsale contract

        _erc20Token     ERC20 token contract address
        _depositAmount  amount to deposit (in the ERC20 token)
        _minReturn      if the change results in an amount smaller than the minimum return, it is cancelled
    */
    function buyERC20(address _erc20Token, uint256 _depositAmount, uint256 _minReturn)
        public
        laterThan(startTime)
        earlierThan(endTime)
        returns (uint256 amount)
    {
        amount = getPurchaseReturn(_erc20Token, _depositAmount);
        assert(amount != 0 && amount >= _minReturn); // ensure the trade gives something in return and meets the minimum requested amount

        ERC20TokenInterface erc20Token = ERC20TokenInterface(_erc20Token);
        assert(erc20Token.transferFrom(msg.sender, beneficiary, _depositAmount)); // transfer _depositAmount funds from the caller in the ERC20 token
        beneficiaryBalances[erc20Token] = safeAdd(beneficiaryBalances[erc20Token], _depositAmount); // increase beneficiary ERC20 balance

        ERC20TokenData data = tokenData[_erc20Token];
        uint256 depositEthValue = safeMul(_depositAmount, data.valueN) / data.valueD;
        handleContribution(msg.sender, depositEthValue, amount);
        Change(_erc20Token, token, msg.sender, _depositAmount, amount);
        return amount;
    }

    /*
        buys the token with ETH
    */
    function buyETH()
        public
        payable
        laterThan(startTime)
        earlierThan(endTime)
        returns (uint256 amount)
    {
        amount = handleETHDeposit(msg.sender, msg.value);
        Change(etherToken, token, msg.sender, msg.value, amount);
        return amount;
    }

    /*
        buys the token with BTCs (Bitcoin Suisse only)
        can only be called before the crowdsale started

        _contributor    account that should receive the new tokens
    */
    function buyBitcoinSuisse(address _contributor)
        public
        payable
        bitcoinSuisseOnly
        bitcoinSuisseEtherCapNotReached(msg.value)
        earlierThan(startTime)
        returns (uint256 amount)
    {
        amount = handleETHDeposit(_contributor, msg.value);
        Change(etherToken, token, msg.sender, msg.value, amount);
        return amount;
    }

    /*
        handles direct ETH deposits (as opposed to ERC20 contributions)

        _contributor    account that should receive the new tokens
        _depositAmount  amount contributed by the account, in wei
    */
    function handleETHDeposit(address _contributor, uint256 _depositAmount) private returns (uint256 amount) {
        require(_depositAmount > 0); // validate input
        amount = getPurchaseReturn(etherToken, _depositAmount);
        assert(amount != 0); // ensure the trade gives something in return

        EtherToken ethToken = EtherToken(etherToken);
        ethToken.deposit.value(_depositAmount)(); // transfer the ether to the ether contract
        assert(ethToken.transfer(beneficiary, _depositAmount)); // transfer the ether to the beneficiary account
        beneficiaryBalances[etherToken] = safeAdd(beneficiaryBalances[etherToken], _depositAmount); // increase beneficiary ETH balance
        handleContribution(_contributor, _depositAmount, amount);
        return amount;
    }

    /*
        handles the generic part of the contribution - regardless of the type of contribution
        assumes that the contribution was already added to the beneficiary account in the different tokens
        updates the reserve balance, total contributed amount and issues new tokens to the contributor and to the beneficiary

        _contributor        account that should the new tokens
        _depositEthValue    amount contributed by the account, in wei
        _return             amount to be issued to the contributor, in the smart token
    */
    function handleContribution(address _contributor, uint256 _depositEthValue, uint256 _return) private {
        // update the reserve balance
        uint8 reserveAllocationPercentage;
        if (totalEtherContributed >= PHASE3_MIN_CONTRIBUTION)
            reserveAllocationPercentage = PHASE3_RESERVE_ALLOCATION;
        else if (totalEtherContributed >= PHASE2_MIN_CONTRIBUTION)
            reserveAllocationPercentage = PHASE2_RESERVE_ALLOCATION;
        else if (totalEtherContributed >= PHASE1_MIN_CONTRIBUTION)
            reserveAllocationPercentage = PHASE1_RESERVE_ALLOCATION;

        uint256 addToReserve = safeMul(_depositEthValue, reserveAllocationPercentage) / 100;
        tokenReserveBalance = safeAdd(tokenReserveBalance, addToReserve);

        // update the total contribution amount
        totalEtherContributed = safeAdd(totalEtherContributed, _depositEthValue);
        // issue new funds to the contributor in the smart token
        token.issue(_contributor, _return);

        // issue tokens to the beneficiary
        uint256 amount = safeMul(100, _return) / (100 - BENEFICIARY_PERCENTAGE);
        amount = safeSub(amount, _return);
        if (amount == 0)
            return;

        token.issue(beneficiary, amount);
    }

    // fallback
    function() payable {
        buyETH();
    }
}


Rename method

Rename method

contract Adjudicator {

	bool public frozen = false;
	uint nonce = 0;
	uint lastTimestamp = 0;
	address owner;
	uint timeout;
	bytes32[] state;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	function Adjudicator(address _owner, uint _timeout) {
		owner = _owner;
		timeout = _timeout;
	}

	function getStateLength() constant returns (uint) {
		return state.length;
	}

	function getStateAt(uint _index) constant returns (bytes32) {
		return state[_index];
	}

	function submit(bytes32[] _state) external onlyOwner notFrozen {
		state = _state;
	}

	function appeal() external onlyOwner notFrozen;// this will have something to do with the rules

	function giveConsent() external onlyOwner notFrozen {
		frozen = true;
	}

	function finalize() external notFrozen returns (bool) {
		if (lastTimestamp > 0 && now > lastTimestamp + timeout) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}

contract Adjudicator {

	bool public frozen = false;
	uint nonce = 0;
	uint lastTimestamp = 0;
	address owner;
	uint timeout;
	bytes32[] state;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	function Adjudicator(address _owner, uint _timeout) {
		owner = _owner;
		timeout = _timeout;
	}

	function getStateLength() constant returns (uint) {
		return state.length;
	}

	function getStateIndex(uint _index) constant returns (bytes32) {
		return state[_index];
	}

	function submit(bytes32[] _state) external onlyOwner notFrozen {
		state = _state;
	}

	function appeal() external onlyOwner notFrozen;// this will have something to do with the rules

	function giveConsent() external onlyOwner notFrozen {
		frozen = true;
	}

	function finalize() external notFrozen returns (bool) {
		if (lastTimestamp > 0 && now > lastTimestamp + timeout) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}


Added Unsuccessful delivery clause

Added Unsuccessful delivery clause

pragma solidity ^0.4.11;

contract transaction {

	address seller;
	address buyer;
	uint value;

	enum State {Created, Confirmed, Disabled} //default state is the first one.
	State state;

	modifier  onlySeller(address person) { require(person == seller); _; }
	modifier checkValue(uint addedValue) { require(addedValue == 2*value); _; }
	modifier inState(State s) { require(s == state); _; }
	modifier  onlyBuyer(address person) { require(person == buyer); _; }

	event purchaseConfirmed();
	event receiveConfirmed();
	event refundConfirmed();
	event itemShipped();

	function transaction () public
	    payable
	{
		seller = msg.sender;
		value = (msg.value*1)/2;
	}

	function confirmPurchase() public
		checkValue(msg.value)
		inState(State.Created)
		payable
	{
		buyer = msg.sender;
		state = State.Confirmed;
		purchaseConfirmed();
		itemShipped();
	}

	function confirmReceived() public
		inState(State.Confirmed)
		onlyBuyer(msg.sender)
	{
		buyer.transfer(value);
		seller.transfer(this.balance);
		state = State.Disabled;
		receiveConfirmed();
	}

	function refundBuyer() public
		inState(State.Confirmed)
		onlySeller(msg.sender)
	{
		buyer.transfer(2*value);
		seller.transfer(this.balance);
		state = State.Disabled;
		refundConfirmed();
	}

	function killContract() public
		onlySeller(msg.sender)
		inState(State.Created)
	{
		selfdestruct(seller);

	}

	function deliveryUnsuccesful() public
		onlySeller(msg.sender)
		inState(State.Confirmed)
	{
		buyer.transfer(value*2);
		selfdestruct(seller);
	}

}

pragma solidity ^0.4.11;

contract transaction {

	address seller;
	address buyer;
	uint value;

	enum State {Created, Confirmed, Disabled}
	State state;

	modifier  onlySeller(address person) { require(person == seller); _; }
	modifier checkValue(uint addedValue) { require(addedValue == 2*value); _; }
	modifier inState(State s) { require(s == state); _; }
	modifier  onlyBuyer(address person) { require(person == buyer); _; }

	event purchaseConfirmed();
	event receiveConfirmed();
	event refundConfirmed();

	function transaction () public
	    payable
	{
		seller = msg.sender;
		value = (msg.value*1)/2;
	}

	function confirmPurchase() public
		checkValue(msg.value)
		inState(State.Created)
		payable
	{
		buyer = msg.sender;
		state = State.Confirmed;
		purchaseConfirmed();
	}

	function confirmReceived() public
		inState(State.Confirmed)
		onlyBuyer(msg.sender)
	{
		buyer.transfer(value);
		seller.transfer(this.balance);
		state = State.Disabled;
		receiveConfirmed();
	}

	function refundBuyer() public
		inState(State.Confirmed)
		onlySeller(msg.sender)
	{
		buyer.transfer(2*value);
		seller.transfer(this.balance);
		state = State.Disabled;
		refundConfirmed();
	}

	function killContract() public
		onlySeller(msg.sender)
		inState(State.Created)
	{
		selfdestruct(seller);
	}

}


Revert to calling `bid(receiver)` instead of `privateBid(receiver)`

pragma solidity ^0.4.11;

import './token.sol';

/// @title Dutch auction contract - distribution of tokens using an auction.
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract DutchAuction {
    /*
    Auction for the TKN Token.
    */

    /*
     *  Storage
     */

    CustomToken public token;
    address public owner;

    // Price function parameters
    uint public price_factor;
    uint public price_const;

    // For calculating elapsed time for price
    uint public start_time;
    uint public end_time;
    uint public start_block;

    // Keep track of funds claimed after auction has ended
    uint public funds_claimed;

    // Total number of tokens that will be auctioned
    uint public tokens_auctioned;

    // Wei per TKN (Tei * multiplier)
    uint public final_price;

    mapping (address => uint) public bids;

    Stages public stage;

    // Terminology:
    // 1 token unit = Tei
    // 1 token = TKN = Tei * multiplier
    // multiplier set from token's number of decimals (i.e. 10**decimals)
    uint public multiplier;

    // TODO - remove after testing
    uint rounding_error_tokens;

    /*
     *  Enums
     */
    enum Stages {
        AuctionDeployed,
        AuctionSetUp,
        AuctionStarted,
        AuctionEnded,
        TokensDistributed,
        TradingStarted
    }

    /*
     *  Modifiers
     */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    modifier isOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier isValidPayload() {
        require(msg.data.length == 0 || msg.data.length == 4 || msg.data.length == 36);
        _;
    }

    /*
     *  Events
     */

    event Deployed(address indexed _auction, uint indexed _price_factor, uint indexed _price_const);
    event Setup();
    event SettingsChanged(uint indexed _price_factor, uint indexed _price_const);
    event AuctionStarted(uint indexed _start_time, uint indexed _block_number);
    event BidSubmission(address indexed _sender, uint indexed _amount, uint indexed _missing_funds);
    event ClaimedTokens(address indexed _recipient, uint indexed _sent_amount);
    event AuctionEnded(uint indexed _final_price);
    event TokensDistributed();
    event TradingStarted();

    /*
     *  Public functions
     */

    /// @dev Contract constructor function sets .
    /// @param _price_factor Auction price factor.
    /// @param _price_const Auction price divisor constant.
    function DutchAuction(
        uint _price_factor,
        uint _price_const)
        public
    {
        require(this.balance == 0);

        owner = msg.sender;
        stage = Stages.AuctionDeployed;
        Deployed(this, price_factor, price_const);
        changeSettings(_price_factor, _price_const);
    }

    function ()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        bid(msg.sender);
    }

    /// @dev Setup function sets external contracts' addresses.
    /// @param _token Token address.
    function setup(address _token)
        public
        isOwner
        atStage(Stages.AuctionDeployed)
    {
        require(_token != 0x0);
        token = CustomToken(_token);
        require(token.owner() == owner);
        require(token.auction_address() == address(this));

        // Get number of tokens to be auctioned from token auction balance
        tokens_auctioned = token.balanceOf(this);

        // Set number of tokens multiplier from token decimals
        multiplier = 10**uint(token.decimals());

        stage = Stages.AuctionSetUp;
        Setup();

        // Tei auctioned
        assert(tokens_auctioned > multiplier);
    }

    /// @dev Changes auction start price factor before auction is started.
    /// @param _price_factor Updated price factor.
    /// @param _price_const Updated price divisor constant.
    function changeSettings(
        uint _price_factor,
        uint _price_const)
        public
        isOwner
    {
        require(stage == Stages.AuctionDeployed || stage == Stages.AuctionSetUp);
        require(_price_factor > 0);
        require(_price_const > 0);

        price_factor = _price_factor;
        price_const = _price_const;
        SettingsChanged(price_factor, price_const);
    }

    /// @dev Starts auction and sets start_time.
    function startAuction()
        public
        isOwner
        atStage(Stages.AuctionSetUp)
    {
        stage = Stages.AuctionStarted;
        start_time = now;
        start_block = block.number;
        AuctionStarted(start_time, start_block);
    }

    /// --------------------------------- Auction Functions -------------------------------------------

    /// @dev Allows to send a bid to the auction.
    function bid()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        bid(msg.sender);
    }

    /// @dev Allows to send a bid to the auction.
    /// @param receiver Bidder account address.
    function bid(address receiver)
        public
        payable
        isValidPayload
        atStage(Stages.AuctionStarted)
    {
        require(receiver != 0x0);
        require(msg.value > 0);

        uint pre_receiver_funds = bids[receiver];

        // Missing funds without the current bid value
        uint missing_funds = missingFundsToEndAuction(this.balance - msg.value);
        require(msg.value <= missing_funds);

        bids[receiver] += msg.value;
        BidSubmission(receiver, msg.value, missing_funds);

        if (missing_funds == msg.value) {
            // When missing_funds is equal to the big value the auction is ended and finalizeAuction is triggered.
            finalizeAuction();
        }

        assert(bids[receiver] == pre_receiver_funds + msg.value);
    }

    /// @dev Claims tokens for bidder after auction. To be used if tokens can be claimed by bidders, individually.
    function claimTokens()
        public
        atStage(Stages.AuctionEnded)
    {
        claimTokens(msg.sender);
    }

    /// @dev Claims tokens for bidder after auction.
    /// @param receiver Tokens will be assigned to this address if set.
    function claimTokens(address receiver)
        public
        isValidPayload
        atStage(Stages.AuctionEnded)
    {
        require(receiver != 0x0);
        require(bids[receiver] > 0);

        // Number of Tei = bidded_wei / wei_per_TKN * multiplier
        uint num = multiplier * bids[receiver] / final_price;

        // Update funds claimed with full bidded amount
        // rounding errors are included to not block the contract
        funds_claimed += bids[receiver];

        // Set receiver bid to 0 before assigning tokens
        bids[receiver] = 0;

        token.transfer(receiver, num);

        ClaimedTokens(receiver, num);

        // Test for a correct claimed tokens calculation
        /* TODO remove this after testing */
        uint auction_unclaimed_tokens = token.balanceOf(this);

        uint unclaimed_tokens = (this.balance - funds_claimed) * multiplier / final_price;
        unclaimed_tokens += rounding_error_tokens;

        if(auction_unclaimed_tokens != unclaimed_tokens) {
            rounding_error_tokens += 1;
            unclaimed_tokens += 1;
        }
        assert(auction_unclaimed_tokens == unclaimed_tokens);
        /* End of removable test */

        if (funds_claimed == this.balance) {
            stage = Stages.TokensDistributed;
            TokensDistributed();
            transferFundsToOwner();
        }

        assert(num == token.balanceOf(receiver));
        assert(bids[receiver] == 0);
    }

    /*
     *  Private functions
     */

    /// @dev Finalize auction and set the final token price.
    function finalizeAuction()
        private
        atStage(Stages.AuctionStarted)
    {
        final_price = calcTokenPrice();
        end_time = now;
        stage = Stages.AuctionEnded;
        AuctionEnded(final_price);

        assert(final_price > 0);
    }

    /// @dev Transfer auction balance to the token.
    function transferFundsToOwner()
        private
        atStage(Stages.TokensDistributed)
    {
        uint pre_balance = this.balance;

        owner.transfer(this.balance);

        stage = Stages.TradingStarted;
        TradingStarted();

        assert(this.balance == 0);
        assert(owner.balance >= pre_balance);
    }

    /// @dev Calculates the token price at the current timestamp during the auction; elapsed time = 0 before auction starts.
    /// @dev At AuctionDeployed the price is 1, because multiplier is 0
    /// @return Returns the token price - Wei per TKN.
    function calcTokenPrice()
        constant
        private
        returns (uint)
    {
        uint elapsed;
        if(stage == Stages.AuctionStarted) {
            elapsed = now - start_time;
        }
        return multiplier * price_factor / (elapsed + price_const) + 1;
    }

    /// --------------------------------- Price Functions -------------------------------------------

    /// @dev Calculates current token price.
    /// @return Returns num Wei per TKN (multiplier * Tei).
    function price()
        public
        constant
        returns (uint)
    {
        if (stage == Stages.AuctionEnded ||
            stage == Stages.TokensDistributed ||
            stage == Stages.TradingStarted)
        {
            return 0;
        }
        return calcTokenPrice();
    }

    /// @dev The missing funds amount necessary to end the auction at the current price.
    /// @return Returns the missing funds amount.
    function missingFundsToEndAuction()
        constant
        public
        returns (uint)
    {
        return missingFundsToEndAuction(this.balance);
    }

    /// @dev The missing funds amount necessary to end the auction at the current price, for a provided balance.
    /// @param funds Current balance or current balance without current bid value for bid().
    /// @return Returns the missing funds amount.
    function missingFundsToEndAuction(uint funds)
        constant
        public
        returns (uint)
    {
        uint funds_at_price = tokens_auctioned * price() / multiplier;
        if(funds_at_price < funds) {
            return 0;
        }
        return funds_at_price - funds;
    }
}

pragma solidity ^0.4.11;

import './token.sol';

/// @title Dutch auction contract - distribution of tokens using an auction.
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract DutchAuction {
    /*
    Auction for the TKN Token.
    */

    /*
     *  Storage
     */

    CustomToken public token;
    address public owner;

    // Price function parameters
    uint public price_factor;
    uint public price_const;

    // For calculating elapsed time for price
    uint public start_time;
    uint public end_time;
    uint public start_block;

    // Keep track of funds claimed after auction has ended
    uint public funds_claimed;

    // Total number of tokens that will be auctioned
    uint public tokens_auctioned;

    // Wei per TKN (Tei * multiplier)
    uint public final_price;

    mapping (address => uint) public bids;

    Stages public stage;

    // Terminology:
    // 1 token unit = Tei
    // 1 token = TKN = Tei * multiplier
    // multiplier set from token's number of decimals (i.e. 10**decimals)
    uint public multiplier;

    // TODO - remove after testing
    uint rounding_error_tokens;

    /*
     *  Enums
     */
    enum Stages {
        AuctionDeployed,
        AuctionSetUp,
        AuctionStarted,
        AuctionEnded,
        TokensDistributed,
        TradingStarted
    }

    /*
     *  Modifiers
     */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    modifier isOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier isValidPayload() {
        require(msg.data.length == 4 || msg.data.length == 36);
        _;
    }

    /*
     *  Events
     */

    event Deployed(address indexed _auction, uint indexed _price_factor, uint indexed _price_const);
    event Setup();
    event SettingsChanged(uint indexed _price_factor, uint indexed _price_const);
    event AuctionStarted(uint indexed _start_time, uint indexed _block_number);
    event BidSubmission(address indexed _sender, uint indexed _amount, uint indexed _missing_funds);
    event ClaimedTokens(address indexed _recipient, uint indexed _sent_amount);
    event AuctionEnded(uint indexed _final_price);
    event TokensDistributed();
    event TradingStarted();

    /*
     *  Public functions
     */

    /// @dev Contract constructor function sets .
    /// @param _price_factor Auction price factor.
    /// @param _price_const Auction price divisor constant.
    function DutchAuction(
        uint _price_factor,
        uint _price_const)
        public
    {
        require(this.balance == 0);

        owner = msg.sender;
        stage = Stages.AuctionDeployed;
        Deployed(this, price_factor, price_const);
        changeSettings(_price_factor, _price_const);
    }

    function ()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        privateBid(msg.sender);
    }

    /// @dev Setup function sets external contracts' addresses.
    /// @param _token Token address.
    function setup(address _token)
        public
        isOwner
        atStage(Stages.AuctionDeployed)
    {
        require(_token != 0x0);
        token = CustomToken(_token);
        require(token.owner() == owner);
        require(token.auction_address() == address(this));

        // Get number of tokens to be auctioned from token auction balance
        tokens_auctioned = token.balanceOf(this);

        // Set number of tokens multiplier from token decimals
        multiplier = 10**uint(token.decimals());

        stage = Stages.AuctionSetUp;
        Setup();

        // Tei auctioned
        assert(tokens_auctioned > multiplier);
    }

    /// @dev Changes auction start price factor before auction is started.
    /// @param _price_factor Updated price factor.
    /// @param _price_const Updated price divisor constant.
    function changeSettings(
        uint _price_factor,
        uint _price_const)
        public
        isOwner
    {
        require(stage == Stages.AuctionDeployed || stage == Stages.AuctionSetUp);
        require(_price_factor > 0);
        require(_price_const > 0);

        price_factor = _price_factor;
        price_const = _price_const;
        SettingsChanged(price_factor, price_const);
    }

    /// @dev Starts auction and sets start_time.
    function startAuction()
        public
        isOwner
        atStage(Stages.AuctionSetUp)
    {
        stage = Stages.AuctionStarted;
        start_time = now;
        start_block = block.number;
        AuctionStarted(start_time, start_block);
    }

    /// --------------------------------- Auction Functions -------------------------------------------

    /// @dev Allows to send a bid to the auction.
    function bid()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        privateBid(msg.sender);
    }

    /// @dev Allows to send a bid to the auction.
    /// @param receiver Bidder account address.
    function bid(address receiver)
        public
        payable
        isValidPayload
        atStage(Stages.AuctionStarted)
    {
        privateBid(receiver);
    }

    /// @dev Claims tokens for bidder after auction. To be used if tokens can be claimed by bidders, individually.
    function claimTokens()
        public
        atStage(Stages.AuctionEnded)
    {
        claimTokens(msg.sender);
    }

    /// @dev Claims tokens for bidder after auction.
    /// @param receiver Tokens will be assigned to this address if set.
    function claimTokens(address receiver)
        public
        isValidPayload
        atStage(Stages.AuctionEnded)
    {
        require(receiver != 0x0);
        require(bids[receiver] > 0);

        // Number of Tei = bidded_wei / wei_per_TKN * multiplier
        uint num = multiplier * bids[receiver] / final_price;

        // Update funds claimed with full bidded amount
        // rounding errors are included to not block the contract
        funds_claimed += bids[receiver];

        // Set receiver bid to 0 before assigning tokens
        bids[receiver] = 0;

        token.transfer(receiver, num);

        ClaimedTokens(receiver, num);

        // Test for a correct claimed tokens calculation
        /* TODO remove this after testing */
        uint auction_unclaimed_tokens = token.balanceOf(this);

        uint unclaimed_tokens = (this.balance - funds_claimed) * multiplier / final_price;
        unclaimed_tokens += rounding_error_tokens;

        if(auction_unclaimed_tokens != unclaimed_tokens) {
            rounding_error_tokens += 1;
            unclaimed_tokens += 1;
        }
        assert(auction_unclaimed_tokens == unclaimed_tokens);
        /* End of removable test */

        if (funds_claimed == this.balance) {
            stage = Stages.TokensDistributed;
            TokensDistributed();
            transferFundsToOwner();
        }

        assert(num == token.balanceOf(receiver));
        assert(bids[receiver] == 0);
    }

    /*
     *  Private functions
     */

    function privateBid(address receiver)
        private
        atStage(Stages.AuctionStarted)
    {
        require(receiver != 0x0);
        require(msg.value > 0);

        uint pre_receiver_funds = bids[receiver];

        // Missing funds without the current bid value
        uint missing_funds = missingFundsToEndAuction(this.balance - msg.value);
        require(msg.value <= missing_funds);

        bids[receiver] += msg.value;
        BidSubmission(receiver, msg.value, missing_funds);

        if (missing_funds == msg.value) {
            // When missing_funds is equal to the big value the auction is ended and finalizeAuction is triggered.
            finalizeAuction();
        }

        assert(bids[receiver] == pre_receiver_funds + msg.value);
    }

    /// @dev Finalize auction and set the final token price.
    function finalizeAuction()
        private
        atStage(Stages.AuctionStarted)
    {
        final_price = calcTokenPrice();
        end_time = now;
        stage = Stages.AuctionEnded;
        AuctionEnded(final_price);

        assert(final_price > 0);
    }

    /// @dev Transfer auction balance to the token.
    function transferFundsToOwner()
        private
        atStage(Stages.TokensDistributed)
    {
        uint pre_balance = this.balance;

        owner.transfer(this.balance);

        stage = Stages.TradingStarted;
        TradingStarted();

        assert(this.balance == 0);
        assert(owner.balance >= pre_balance);
    }

    /// @dev Calculates the token price at the current timestamp during the auction; elapsed time = 0 before auction starts.
    /// @dev At AuctionDeployed the price is 1, because multiplier is 0
    /// @return Returns the token price - Wei per TKN.
    function calcTokenPrice()
        constant
        private
        returns (uint)
    {
        uint elapsed;
        if(stage == Stages.AuctionStarted) {
            elapsed = now - start_time;
        }
        return multiplier * price_factor / (elapsed + price_const) + 1;
    }

    /// --------------------------------- Price Functions -------------------------------------------

    /// @dev Calculates current token price.
    /// @return Returns num Wei per TKN (multiplier * Tei).
    function price()
        public
        constant
        returns (uint)
    {
        if (stage == Stages.AuctionEnded ||
            stage == Stages.TokensDistributed ||
            stage == Stages.TradingStarted)
        {
            return 0;
        }
        return calcTokenPrice();
    }

    /// @dev The missing funds amount necessary to end the auction at the current price.
    /// @return Returns the missing funds amount.
    function missingFundsToEndAuction()
        constant
        public
        returns (uint)
    {
        return missingFundsToEndAuction(this.balance);
    }

    /// @dev The missing funds amount necessary to end the auction at the current price, for a provided balance.
    /// @param funds Current balance or current balance without current bid value for bid().
    /// @return Returns the missing funds amount.
    function missingFundsToEndAuction(uint funds)
        constant
        public
        returns (uint)
    {
        uint funds_at_price = tokens_auctioned * price() / multiplier;
        if(funds_at_price < funds) {
            return 0;
        }
        return funds_at_price - funds;
    }
}


Update the informational link (#3703)

Update the informational link (#3703)

(cherry picked from commit 76b538c226df019a1451467d36351b3c61cd4139)

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0-rc.0) (metatx/MinimalForwarder.sol)

pragma solidity ^0.8.0;

import "../utils/cryptography/ECDSA.sol";
import "../utils/cryptography/EIP712.sol";

/**
 * @dev Simple minimal forwarder to be used together with an ERC2771 compatible contract. See {ERC2771Context}.
 *
 * MinimalForwarder is mainly meant for testing, as it is missing features to be a good production-ready forwarder. This
 * contract does not intend to have all the properties that are needed for a sound forwarding system. A fully
 * functioning forwarding system with good properties requires more complexity. We suggest you look at other projects
 * such as the GSN which do have the goal of building a system like that.
 */
contract MinimalForwarder is EIP712 {
    using ECDSA for bytes32;

    struct ForwardRequest {
        address from;
        address to;
        uint256 value;
        uint256 gas;
        uint256 nonce;
        bytes data;
    }

    bytes32 private constant _TYPEHASH =
        keccak256("ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)");

    mapping(address => uint256) private _nonces;

    constructor() EIP712("MinimalForwarder", "0.0.1") {}

    function getNonce(address from) public view returns (uint256) {
        return _nonces[from];
    }

    function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) {
        address signer = _hashTypedDataV4(
            keccak256(abi.encode(_TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data)))
        ).recover(signature);
        return _nonces[req.from] == req.nonce && signer == req.from;
    }

    function execute(ForwardRequest calldata req, bytes calldata signature)
        public
        payable
        returns (bool, bytes memory)
    {
        require(verify(req, signature), "MinimalForwarder: signature does not match request");
        _nonces[req.from] = req.nonce + 1;

        (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(
            abi.encodePacked(req.data, req.from)
        );

        // Validate that the relayer has sent enough gas for the call.
        // See https://ronan.eth.limo/blog/ethereum-gas-dangers/
        if (gasleft() <= req.gas / 63) {
            // We explicitly trigger invalid opcode to consume all gas and bubble-up the effects, since
            // neither revert or assert consume all gas since Solidity 0.8.0
            // https://docs.soliditylang.org/en/v0.8.0/control-structures.html#panic-via-assert-and-error-via-require
            /// @solidity memory-safe-assembly
            assembly {
                invalid()
            }
        }

        return (success, returndata);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0-rc.0) (metatx/MinimalForwarder.sol)

pragma solidity ^0.8.0;

import "../utils/cryptography/ECDSA.sol";
import "../utils/cryptography/EIP712.sol";

/**
 * @dev Simple minimal forwarder to be used together with an ERC2771 compatible contract. See {ERC2771Context}.
 *
 * MinimalForwarder is mainly meant for testing, as it is missing features to be a good production-ready forwarder. This
 * contract does not intend to have all the properties that are needed for a sound forwarding system. A fully
 * functioning forwarding system with good properties requires more complexity. We suggest you look at other projects
 * such as the GSN which do have the goal of building a system like that.
 */
contract MinimalForwarder is EIP712 {
    using ECDSA for bytes32;

    struct ForwardRequest {
        address from;
        address to;
        uint256 value;
        uint256 gas;
        uint256 nonce;
        bytes data;
    }

    bytes32 private constant _TYPEHASH =
        keccak256("ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)");

    mapping(address => uint256) private _nonces;

    constructor() EIP712("MinimalForwarder", "0.0.1") {}

    function getNonce(address from) public view returns (uint256) {
        return _nonces[from];
    }

    function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) {
        address signer = _hashTypedDataV4(
            keccak256(abi.encode(_TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data)))
        ).recover(signature);
        return _nonces[req.from] == req.nonce && signer == req.from;
    }

    function execute(ForwardRequest calldata req, bytes calldata signature)
        public
        payable
        returns (bool, bytes memory)
    {
        require(verify(req, signature), "MinimalForwarder: signature does not match request");
        _nonces[req.from] = req.nonce + 1;

        (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(
            abi.encodePacked(req.data, req.from)
        );

        // Validate that the relayer has sent enough gas for the call.
        // See https://ronan.eth.link/blog/ethereum-gas-dangers/
        if (gasleft() <= req.gas / 63) {
            // We explicitly trigger invalid opcode to consume all gas and bubble-up the effects, since
            // neither revert or assert consume all gas since Solidity 0.8.0
            // https://docs.soliditylang.org/en/v0.8.0/control-structures.html#panic-via-assert-and-error-via-require
            /// @solidity memory-safe-assembly
            assembly {
                invalid()
            }
        }

        return (success, returndata);
    }
}


Switch to bool.

Switch to bool.

//Most, basic default, standardised Token contract.
//Based on standardised APIs & slightly extended. https://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs
//adds AddressApproval & AddressApprovalOnce events
//approve & approveOnce works on premise that approved always takes precedence.
//adds unapprove to basic coin interface.

contract Coin {
    function sendCoin(uint _value, address _to) returns (bool _success) {}
    function sendCoinFrom(address _from, uint _value, address _to) returns (bool _success) {}
    function coinBalance() constant returns (uint _r) {}
    function coinBalanceOf(address _addr) constant returns (uint _r) {}
    function approve(address _addr) {}
    function approveOnce(address _addr, uint256 _maxValue) {}
    function unapprove(address _addr) {}
    function isApproved(address _proxy) constant returns (bool _r) {}
    function isApprovedFor(address _target, address _proxy) constant returns (bool _r) {}
}

contract Token is Coin {

    function Token(uint _initialAmount) {
        balances[msg.sender] = _initialAmount;
    }

    event CoinTransfer(address indexed from, address indexed to, uint256 value);
    event AddressApproval(address indexed from, address indexed to, bool result);
    event AddressApprovalOnce(address indexed from, address indexed to, uint256 value);

    function sendCoin(uint _value, address _to) returns (bool _success) {
        if (balances[msg.sender] >= _value) {
            balances[msg.sender] -= _value;
            balances[_to] += _value;
            CoinTransfer(msg.sender, _to, _value);
            return true;
        } else { return false; }
    }

    function sendCoinFrom(address _from, uint _value, address _to) returns (bool _success) {
        if (balances[_from] >= _value) {
            bool transfer = false;
            if(approved[_from][msg.sender]) {
                transfer = true;
            } else {
                if(_value < approved_once[_from][msg.sender]) {
                    transfer = true;
                    approved_once[_from][msg.sender] = 0; //reset
                }
            }

            if(transfer == true) {
                balances[_from] -= _value;
                balances[_to] += _value;
                CoinTransfer(_from, _to, _value);
                return true;
            } else { return false; }
        }
    }

    function coinBalance() constant returns (uint _r) {
        return balances[msg.sender];
    }

    function coinBalanceOf(address _addr) constant returns (uint _r) {
        return balances[_addr];
    }

    function approve(address _addr) {
        approved[msg.sender][_addr] = true;
        AddressApproval(msg.sender, _addr, true);
    }

    function approveOnce(address _addr, uint256 _maxValue) {
        approved_once[msg.sender][_addr] = _maxValue;
        AddressApprovalOnce(msg.sender, _addr, _maxValue);
    }

    function unapprove(address _addr) {
        approved[msg.sender][_addr] = false;
        approved_once[msg.sender][_addr] = 0;
        AddressApproval(msg.sender, _addr, false);
        AddressApprovalOnce(msg.sender, _addr, 0);
    }

    function isApproved(address _proxy) constant returns (bool _r) {
        if(approved[msg.sender][_proxy] == true || approved_once[msg.sender][_proxy] > 0) {
            return true;
        }
    }

    function isApprovedFor(address _target, address _proxy) constant returns (bool _r) {
        if(approved[_target][_proxy] == true || approved_once[_target][_proxy] > 0) {
            return true;
        }
    }

    mapping (address => uint) public balances;
    mapping (address => mapping (address => bool)) public approved;
    mapping (address => mapping (address => uint256)) public approved_once;
}

//Most, basic default, standardised Token contract.
//Based on standardised APIs & slightly extended. https://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs
//adds AddressApproval & AddressApprovalOnce events
//approve & approveOnce works on premise that approved always takes precedence.
//adds unapprove to basic coin interface.

contract Coin {
    function sendCoin(uint _value, address _to) returns (bool _success) {}
    function sendCoinFrom(address _from, uint _value, address _to) returns (bool _success) {}
    function coinBalance() constant returns (uint _r) {}
    function coinBalanceOf(address _addr) constant returns (uint _r) {}
    function approve(address _addr) {}
    function approveOnce(address _addr, uint256 _maxValue) {}
    function unapprove(address _addr) {}
    function isApproved(address _proxy) constant returns (bool _r) {}
    function isApprovedFor(address _target, address _proxy) constant returns (bool _r) {}
}

contract Token is Coin {

    function Token(uint _initialAmount) {
        balances[msg.sender] = _initialAmount;
    }

    event CoinTransfer(address indexed from, address indexed to, uint256 value);
    event AddressApproval(address indexed from, address indexed to, bool result);
    event AddressApprovalOnce(address indexed from, address indexed to, uint256 value);

    function sendCoin(uint _value, address _to) returns (bool _success) {
        if (balances[msg.sender] >= _value) {
            balances[msg.sender] -= _value;
            balances[_to] += _value;
            CoinTransfer(msg.sender, _to, _value);
            return true;
        } else { return false; }
    }

    function sendCoinFrom(address _from, uint _value, address _to) returns (bool _success) {
        if (balances[_from] >= _value) {
            var transfer = false;
            if(approved[_from][msg.sender]) {
                transfer = true;
            } else {
                if(_value < approved_once[_from][msg.sender]) {
                    transfer = true;
                    approved_once[_from][msg.sender] = 0; //reset
                }
            }

            if(transfer == true) {
                balances[_from] -= _value;
                balances[_to] += _value;
                CoinTransfer(_from, _to, _value);
                return true;
            } else { return false; }
        }
    }

    function coinBalance() constant returns (uint _r) {
        return balances[msg.sender];
    }

    function coinBalanceOf(address _addr) constant returns (uint _r) {
        return balances[_addr];
    }

    function approve(address _addr) {
        approved[msg.sender][_addr] = true;
        AddressApproval(msg.sender, _addr, true);
    }

    function approveOnce(address _addr, uint256 _maxValue) {
        approved_once[msg.sender][_addr] = _maxValue;
        AddressApprovalOnce(msg.sender, _addr, _maxValue);
    }

    function unapprove(address _addr) {
        approved[msg.sender][_addr] = false;
        approved_once[msg.sender][_addr] = 0;
        AddressApproval(msg.sender, _addr, false);
        AddressApprovalOnce(msg.sender, _addr, 0);
    }

    function isApproved(address _proxy) constant returns (bool _r) {
        if(approved[msg.sender][_proxy] == true || approved_once[msg.sender][_proxy] > 0) {
            return true;
        }
    }

    function isApprovedFor(address _target, address _proxy) constant returns (bool _r) {
        if(approved[_target][_proxy] == true || approved_once[_target][_proxy] > 0) {
            return true;
        }
    }

    mapping (address => uint) public balances;
    mapping (address => mapping (address => bool)) public approved;
    mapping (address => mapping (address => uint256)) public approved_once;
}