Update function lnUpperBound32

Update function lnUpperBound32

1. Improve the accuracy of testing whether the input is smaller than e^1, e^2, e^3 or neither.
2. Add and use function ceilLog2 (this is essentially just for coding clarification).

pragma solidity ^0.4.11;
import './SafeMath.sol';
import './interfaces/IBancorFormula.sol';

/*
    Open issues:
    - The formula is not yet super accurate, especially for very small/very high ratios
    - Improve dynamic precision support
*/

contract BancorFormula is IBancorFormula, SafeMath {

    uint256 constant ONE = 1;
    uint256 constant TWO = 2;
    uint256 constant MAX_FIXED_EXP_32 = 0x386bfdba29;
    string public version = '0.2';

    function BancorFormula() {
    }

    /**
        @dev given a token supply, reserve, CRR and a deposit amount (in the reserve token), calculates the return for a given change (in the main token)

        Formula:
        Return = _supply * ((1 + _depositAmount / _reserveBalance) ^ (_reserveRatio / 100) - 1)

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _depositAmount      deposit amount, in reserve token

        @return purchase return amount
    */
    function calculatePurchaseReturn(uint256 _supply, uint256 _reserveBalance, uint8 _reserveRatio, uint256 _depositAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100);

        // special case for 0 deposit amount
        if (_depositAmount == 0)
            return 0;

        uint256 baseN = safeAdd(_depositAmount, _reserveBalance);
        uint256 temp;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp = safeMul(_supply, baseN) / _reserveBalance;
            return safeSub(temp, _supply);
        }

        uint8 precision = calculateBestPrecision(baseN, _reserveBalance, _reserveRatio, 100);
        uint256 resN = power(baseN, _reserveBalance, _reserveRatio, 100, precision);
        temp = safeMul(_supply, resN) >> precision;
        return safeSub(temp, _supply);
     }

    /**
        @dev given a token supply, reserve, CRR and a sell amount (in the main token), calculates the return for a given change (in the reserve token)

        Formula:
        Return = _reserveBalance * (1 - (1 - _sellAmount / _supply) ^ (1 / (_reserveRatio / 100)))

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _sellAmount         sell amount, in the token itself

        @return sale return amount
    */
    function calculateSaleReturn(uint256 _supply, uint256 _reserveBalance, uint8 _reserveRatio, uint256 _sellAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100 && _sellAmount <= _supply);

        // special case for 0 sell amount
        if (_sellAmount == 0)
            return 0;

        uint256 baseD = safeSub(_supply, _sellAmount);
        uint256 temp1;
        uint256 temp2;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp1 = safeMul(_reserveBalance, _supply);
            temp2 = safeMul(_reserveBalance, baseD);
            return safeSub(temp1, temp2) / _supply;
        }

        // special case for selling the entire supply
        if (_sellAmount == _supply)
            return _reserveBalance;

        uint8 precision = calculateBestPrecision(_supply, baseD, 100, _reserveRatio);
        uint256 resN = power(_supply, baseD, 100, _reserveRatio, precision);
        temp1 = safeMul(_reserveBalance, resN);
        temp2 = safeMul(_reserveBalance, ONE << precision);
        return safeSub(temp1, temp2) / resN;
    }

    /**
        calculateBestPrecision
        Predicts the highest precision which can be used in order to compute "base^exp" without exceeding 256 bits in any of the intermediate computations.
        Instead of calculating "base ^ exp", we calculate "e ^ (ln(base) * exp)".
        The value of ln(base) is represented with an integer slightly smaller than ln(base) * 2 ^ precision.
        The larger the precision is, the more accurately this value represents the real value.
        However, function fixedExpUnsafe(x), which calculates e ^ x, is limited to a maximum value of x.
        The limit depends on the precision (e.g, for precision = 32, the maximum value of x is MAX_FIXED_EXP_32).
        Hence before calling the 'power' function, we need to estimate an upper-bound for ln(base) * exponent.
        Of course, we should later assert that the value passed to fixedExpUnsafe is not larger than MAX_FIXED_EXP(precision).
        Due to this assertion (made in function fixedExp), functions calculateBestPrecision and fixedExp are tightly coupled.
        Note that the outcome of this function only affects the accuracy of the computation of "base ^ exp".
        Therefore, we do not need to assert that no intermediate result exceeds 256 bits (nor in this function, neither in any of the functions down the calling tree).
    */
    function calculateBestPrecision(uint256 _baseN, uint256 _baseD, uint256 _expN, uint256 _expD) constant returns (uint8) {
        uint8 precision;
        uint256 maxExp = MAX_FIXED_EXP_32;
        uint256 maxVal = lnUpperBound32(_baseN,_baseD) * _expN;
        for (precision = 0; precision < 32; precision += 2) {
            if (maxExp < (maxVal << precision) / _expD)
                break;
            maxExp = (maxExp * 0xeb5ec5975959c565) >> (64-2);
        }
        if (precision == 0)
            return 32;
        return precision+32-2;
    }

    /**
        @dev calculates (_baseN / _baseD) ^ (_expN / _expD)
        Returns result upshifted by precision

        This method is overflow-safe
    */
    function power(uint256 _baseN, uint256 _baseD, uint256 _expN, uint256 _expD, uint8 _precision) constant returns (uint256) {
        uint256 logbase = ln(_baseN, _baseD, _precision);
        // Not using safeDiv here, since safeDiv protects against
        // precision loss. It's unavoidable, however
        // Both `ln` and `fixedExp` are overflow-safe.
        return fixedExp(safeMul(logbase, _expN) / _expD, _precision);
    }

    /**
        input range:
            - numerator: [1, uint256_max >> precision]
            - denominator: [1, uint256_max >> precision]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds
    */
    function ln(uint256 _numerator, uint256 _denominator, uint8 _precision) public constant returns (uint256) {
        // denominator > numerator: less than one yields negative values. Unsupported
        assert(_denominator <= _numerator);

        // log(1) is the lowest we can go
        assert(_denominator != 0 && _numerator != 0);

        // Upper bits are scaled off by precision
        uint256 MAX_VAL = ONE << (256 - _precision);
        assert(_numerator < MAX_VAL);
        assert(_denominator < MAX_VAL);

        return fixedLoge( (_numerator << _precision) / _denominator, _precision);
    }

    /**
        lnUpperBound32
        Takes a rational number "baseN / baseD" as input.
        Returns an integer upper-bound of the natural logarithm of the input scaled by 2^32.
        We do this by calculating "Ceiling(log2(baseN / baseD)) * Ceiling(ln(2) * 2^32)".
        For small values of "baseN / baseD", this sometimes yields a bad upper-bound approximation.
        We therefore cover these cases (and a few more) manually.
        Complexity is O(log(input bit-length)).
    */
    function lnUpperBound32(uint256 _baseN, uint256 _baseD) constant returns (uint256) {
        assert(_baseN > _baseD);

        uint256 scaledBaseN = _baseN << 32;
        if (scaledBaseN <= _baseD *  0x2b7e15162) // _baseN / _baseD < e^1 (floorLog2 will return 0 if _baseN / _baseD < 2)
            return uint256(1) << 32;
        if (scaledBaseN <= _baseD *  0x763992e35) // _baseN / _baseD < e^2 (floorLog2 will return 1 if _baseN / _baseD < 4)
            return uint256(2) << 32;
        if (scaledBaseN <= _baseD * 0x1415e5bf6f) // _baseN / _baseD < e^3 (floorLog2 will return 2 if _baseN / _baseD < 8)
            return uint256(3) << 32;

        return ceilLog2(_baseN, _baseD) * 0xb17217f8;
    }

    /**
        input range:
            [0x100000000, uint256_max]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

        Since `fixedLog2_min` output range is max `0xdfffffffff`
        (40 bits, or 5 bytes), we can use a very large approximation
        for `ln(2)`. This one is used since it's the max accuracy
        of Python `ln(2)`

        0xb17217f7d1cf78 = ln(2) * (1 << 56)
    */
    function fixedLoge(uint256 _x, uint8 _precision) constant returns (uint256) {
        // cannot represent negative numbers (below 1)
        assert(_x >= ONE << _precision);

        uint256 log2 = fixedLog2(_x, _precision);
        return (log2 * 0xb17217f7d1cf78) >> 56;
    }

    /**
        Returns log2(x >> 32) << 32 [1]
        So x is assumed to be already upshifted 32 bits, and
        the result is also upshifted 32 bits.

        [1] The function returns a number which is lower than the
        actual value

        input-range :
            [0x100000000, uint256_max]
        output-range:
            [0,0xdfffffffff]

        This method asserts outside of bounds

    */
    function fixedLog2(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 fixedOne = ONE << _precision;
        uint256 fixedTwo = TWO << _precision;

        // Numbers below 1 are negative.
        assert( _x >= fixedOne);

        uint256 hi = 0;
        while (_x >= fixedTwo) {
            _x >>= 1;
            hi += fixedOne;
        }

        for (uint8 i = 0; i < _precision; ++i) {
            _x = (_x * _x) / fixedOne;
            if (_x >= fixedTwo) {
                _x >>= 1;
                hi += ONE << (_precision - 1 - i);
            }
        }

        return hi;
    }

    /**
        ceilLog2
        Takes a rational number "baseN / baseD" as input.
        Returns the smallest integer larger than or equal to the binary logarithm of the input.
        Complexity is O(log(input bit-length)).
    */
    function ceilLog2(uint256 _baseN, uint256 _baseD) constant returns (uint256) {
        return floorLog2((_baseN - 1) / _baseD) + 1;
    }

    /**
        floorLog2
        Takes a natural number (n) as input.
        Returns the largest integer smaller than or equal to the binary logarithm of the input.
        Complexity is O(log(input bit-length)).
    */
    function floorLog2(uint256 _n) constant returns (uint256) {
        uint8 t = 0;
        for (uint8 s = 128; s > 0; s >>= 1) {
            if (_n >= (ONE << s)) {
                _n >>= s;
                t |= s;
            }
        }

        return t;
    }

    /**
        fixedExp is a 'protected' version of `fixedExpUnsafe`, which asserts instead of overflows.
        The maximum value which can be passed to fixedExpUnsafe depends on the precision used.
        The following array maps each precision between 0 and 63 to the maximum value permitted:
        maxExpArray = {
            0xc1               ,0x17a              ,0x2e5              ,0x5ab              ,
            0xb1b              ,0x15bf             ,0x2a0c             ,0x50a2             ,
            0x9aa2             ,0x1288c            ,0x238b2            ,0x4429a            ,
            0x82b78            ,0xfaadc            ,0x1e0bb8           ,0x399e96           ,
            0x6e7f88           ,0xd3e7a3           ,0x1965fea          ,0x30b5057          ,
            0x5d681f3          ,0xb320d03          ,0x15784a40         ,0x292c5bdd         ,
            0x4ef57b9b         ,0x976bd995         ,0x122624e32        ,0x22ce03cd5        ,
            0x42beef808        ,0x7ffffffff        ,0xf577eded5        ,0x1d6bd8b2eb       ,
            0x386bfdba29       ,0x6c3390ecc8       ,0xcf8014760f       ,0x18ded91f0e7      ,
            0x2fb1d8fe082      ,0x5b771955b36      ,0xaf67a93bb50      ,0x15060c256cb2     ,
            0x285145f31ae5     ,0x4d5156639708     ,0x944620b0e70e     ,0x11c592761c666    ,
            0x2214d10d014ea    ,0x415bc6d6fb7dd    ,0x7d56e76777fc5    ,0xf05dc6b27edad    ,
            0x1ccf4b44bb4820   ,0x373fc456c53bb7   ,0x69f3d1c921891c   ,0xcb2ff529eb71e4   ,
            0x185a82b87b72e95  ,0x2eb40f9f620fda6  ,0x5990681d961a1ea  ,0xabc25204e02828d  ,
            0x14962dee9dc97640 ,0x277abdcdab07d5a7 ,0x4bb5ecca963d54ab ,0x9131271922eaa606 ,
            0x116701e6ab0cd188d,0x215f77c045fbe8856,0x3ffffffffffffffff,0x7abbf6f6abb9d087f,
        };
        Since we cannot use an array of constants, we need to approximate the maximum value dynamically.
        For a precision of 32, the maximum value permitted is MAX_FIXED_EXP_32.
        For each additional precision unit, the maximum value permitted increases by approximately 1.9.
        So in order to calculate it, we need to multiply MAX_FIXED_EXP_32 by 1.9 for every additional precision unit.
        And in order to optimize for speed, we multiply MAX_FIXED_EXP_32 by 1.9^2 for every 2 additional precision units.
        Hence the general function for mapping a given precision to the maximum value permitted is:
        - precision = [32, 34, 36, ..., 62]
        - MaxFixedExp(precision) = MAX_FIXED_EXP_32 * 3.61 ^ (precision / 2 - 16)
        Since we cannot use non-integers, we do MAX_FIXED_EXP_32 * 361 ^ (precision / 2 - 16) / 100 ^ (precision / 2 - 16).
        But there is a better approximation, because this "1.9" factor in fact extends beyond a single decimal digit.
        So instead, we use 0xeb5ec5975959c565 / 0x4000000000000000, which yields maximum values quite close to real ones:
        maxExpArray = {
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            0x386bfdba29       ,-------------------,0xcf8014760e       ,-------------------,
            0x2fb1d8fe07b      ,-------------------,0xaf67a93bb37      ,-------------------,
            0x285145f31a8f     ,-------------------,0x944620b0e5ee     ,-------------------,
            0x2214d10d0112e    ,-------------------,0x7d56e7677738e    ,-------------------,
            0x1ccf4b44bb20d0   ,-------------------,0x69f3d1c9210d27   ,-------------------,
            0x185a82b87b5b294  ,-------------------,0x5990681d95d4371  ,-------------------,
            0x14962dee9dbd672b ,-------------------,0x4bb5ecca961fb9bf ,-------------------,
            0x116701e6ab0967080,-------------------,0x3fffffffffffe6652,-------------------,
        };
    */
    function fixedExp(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 maxExp = MAX_FIXED_EXP_32;
        for (uint8 p = 32; p < _precision; p += 2)
            maxExp = (maxExp * 0xeb5ec5975959c565) >> (64-2);

        assert(_x <= maxExp);
        return fixedExpUnsafe(_x, _precision);
    }

    /**
        fixedExp
        Calculates e ^ x according to maclauren summation:

        e^x = 1 + x + x ^ 2 / 2!...+ x ^ n / n!

        and returns e ^ (x >> 32) << 32, that is, upshifted for accuracy

        Input range:
            - Function ok at    <= 242329958953
            - Function fails at >= 242329958954

        This method is is visible for testcases, but not meant for direct use.

        The values in this method been generated via the following python snippet:

        def calculateFactorials():
            """Method to print out the factorials for fixedExp"""

            ni = []
            ni.append(295232799039604140847618609643520000000) # 34!
            ITERATIONS = 34
            for n in range(1, ITERATIONS, 1) :
                ni.append(math.floor(ni[n - 1] / n))
            print( "\n        ".join(["xi = (xi * _x) >> _precision;\n        res += xi * %s;" % hex(int(x)) for x in ni]))

    */
    function fixedExpUnsafe(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 xi = _x;
        uint256 res = uint256(0xde1bc4d19efcac82445da75b00000000) << _precision;

        res += xi * 0xde1bc4d19efcac82445da75b00000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x6f0de268cf7e5641222ed3ad80000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x2504a0cd9a7f7215b60f9be480000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9412833669fdc856d83e6f920000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1d9d4d714865f4de2b3fafea0000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x4ef8ce836bba8cfb1dff2a70000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xb481d807d1aa66d04490610000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x16903b00fa354cda08920c2000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x281cdaac677b334ab9e732000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x402e2aad725eb8778fd85000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x5d5a6c9f31fe2396a2af000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x7c7890d442a82f73839400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9931ed54034526b58e400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaf147cf24ce150cf7e00000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa200000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa20000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xafc441338061b2820000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9c3cabbc0056d790000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x839168328705c30000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x694120286c049c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x50319e98b3d2c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x3a52a1e36b82000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x289286e0fce000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> _precision;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> _precision;
        res += xi * 0x650139600;
        xi = (xi * _x) >> _precision;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> _precision;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> _precision;
        res += xi * 0x8c40;
        xi = (xi * _x) >> _precision;
        res += xi * 0x462;
        xi = (xi * _x) >> _precision;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }
}

pragma solidity ^0.4.11;
import './SafeMath.sol';
import './interfaces/IBancorFormula.sol';

/*
    Open issues:
    - The formula is not yet super accurate, especially for very small/very high ratios
    - Improve dynamic precision support
*/

contract BancorFormula is IBancorFormula, SafeMath {

    uint256 constant ONE = 1;
    uint256 constant TWO = 2;
    uint256 constant MAX_FIXED_EXP_32 = 0x386bfdba29;
    string public version = '0.2';

    function BancorFormula() {
    }

    /**
        @dev given a token supply, reserve, CRR and a deposit amount (in the reserve token), calculates the return for a given change (in the main token)

        Formula:
        Return = _supply * ((1 + _depositAmount / _reserveBalance) ^ (_reserveRatio / 100) - 1)

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _depositAmount      deposit amount, in reserve token

        @return purchase return amount
    */
    function calculatePurchaseReturn(uint256 _supply, uint256 _reserveBalance, uint8 _reserveRatio, uint256 _depositAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100);

        // special case for 0 deposit amount
        if (_depositAmount == 0)
            return 0;

        uint256 baseN = safeAdd(_depositAmount, _reserveBalance);
        uint256 temp;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp = safeMul(_supply, baseN) / _reserveBalance;
            return safeSub(temp, _supply);
        }

        uint8 precision = calculateBestPrecision(baseN, _reserveBalance, _reserveRatio, 100);
        uint256 resN = power(baseN, _reserveBalance, _reserveRatio, 100, precision);
        temp = safeMul(_supply, resN) >> precision;
        return safeSub(temp, _supply);
     }

    /**
        @dev given a token supply, reserve, CRR and a sell amount (in the main token), calculates the return for a given change (in the reserve token)

        Formula:
        Return = _reserveBalance * (1 - (1 - _sellAmount / _supply) ^ (1 / (_reserveRatio / 100)))

        @param _supply             token total supply
        @param _reserveBalance     total reserve
        @param _reserveRatio       constant reserve ratio, 1-100
        @param _sellAmount         sell amount, in the token itself

        @return sale return amount
    */
    function calculateSaleReturn(uint256 _supply, uint256 _reserveBalance, uint8 _reserveRatio, uint256 _sellAmount) public constant returns (uint256) {
        // validate input
        require(_supply != 0 && _reserveBalance != 0 && _reserveRatio > 0 && _reserveRatio <= 100 && _sellAmount <= _supply);

        // special case for 0 sell amount
        if (_sellAmount == 0)
            return 0;

        uint256 baseD = safeSub(_supply, _sellAmount);
        uint256 temp1;
        uint256 temp2;

        // special case if the CRR = 100
        if (_reserveRatio == 100) {
            temp1 = safeMul(_reserveBalance, _supply);
            temp2 = safeMul(_reserveBalance, baseD);
            return safeSub(temp1, temp2) / _supply;
        }

        // special case for selling the entire supply
        if (_sellAmount == _supply)
            return _reserveBalance;

        uint8 precision = calculateBestPrecision(_supply, baseD, 100, _reserveRatio);
        uint256 resN = power(_supply, baseD, 100, _reserveRatio, precision);
        temp1 = safeMul(_reserveBalance, resN);
        temp2 = safeMul(_reserveBalance, ONE << precision);
        return safeSub(temp1, temp2) / resN;
    }

    /**
        calculateBestPrecision
        Predicts the highest precision which can be used in order to compute "base^exp" without exceeding 256 bits in any of the intermediate computations.
        Instead of calculating "base ^ exp", we calculate "e ^ (ln(base) * exp)".
        The value of ln(base) is represented with an integer slightly smaller than ln(base) * 2 ^ precision.
        The larger the precision is, the more accurately this value represents the real value.
        However, function fixedExpUnsafe(x), which calculates e ^ x, is limited to a maximum value of x.
        The limit depends on the precision (e.g, for precision = 32, the maximum value of x is MAX_FIXED_EXP_32).
        Hence before calling the 'power' function, we need to estimate an upper-bound for ln(base) * exponent.
        Of course, we should later assert that the value passed to fixedExpUnsafe is not larger than MAX_FIXED_EXP(precision).
        Due to this assertion (made in function fixedExp), functions calculateBestPrecision and fixedExp are tightly coupled.
        Note that the outcome of this function only affects the accuracy of the computation of "base ^ exp".
        Therefore, we do not need to assert that no intermediate result exceeds 256 bits (nor in this function, neither in any of the functions down the calling tree).
    */
    function calculateBestPrecision(uint256 _baseN, uint256 _baseD, uint256 _expN, uint256 _expD) constant returns (uint8) {
        uint8 precision;
        uint256 maxExp = MAX_FIXED_EXP_32;
        uint256 maxVal = lnUpperBound32(_baseN,_baseD) * _expN;
        for (precision = 0; precision < 32; precision += 2) {
            if (maxExp < (maxVal << precision) / _expD)
                break;
            maxExp = (maxExp * 0xeb5ec5975959c565) >> (64-2);
        }
        if (precision == 0)
            return 32;
        return precision+32-2;
    }

    /**
        @dev calculates (_baseN / _baseD) ^ (_expN / _expD)
        Returns result upshifted by precision

        This method is overflow-safe
    */
    function power(uint256 _baseN, uint256 _baseD, uint256 _expN, uint256 _expD, uint8 _precision) constant returns (uint256) {
        uint256 logbase = ln(_baseN, _baseD, _precision);
        // Not using safeDiv here, since safeDiv protects against
        // precision loss. It's unavoidable, however
        // Both `ln` and `fixedExp` are overflow-safe.
        return fixedExp(safeMul(logbase, _expN) / _expD, _precision);
    }

    /**
        input range:
            - numerator: [1, uint256_max >> precision]
            - denominator: [1, uint256_max >> precision]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds
    */
    function ln(uint256 _numerator, uint256 _denominator, uint8 _precision) public constant returns (uint256) {
        // denominator > numerator: less than one yields negative values. Unsupported
        assert(_denominator <= _numerator);

        // log(1) is the lowest we can go
        assert(_denominator != 0 && _numerator != 0);

        // Upper bits are scaled off by precision
        uint256 MAX_VAL = ONE << (256 - _precision);
        assert(_numerator < MAX_VAL);
        assert(_denominator < MAX_VAL);

        return fixedLoge( (_numerator << _precision) / _denominator, _precision);
    }

    /**
        lnUpperBound32
        Takes a rational number "baseN / baseD" as input.
        Returns an integer upper-bound of the natural logarithm of the input scaled by 2^32.
        We do this by calculating "UpperBound(log2(baseN / baseD)) * Ceiling(ln(2) * 2^32)".
        We calculate "UpperBound(log2(baseN / baseD))" as "Floor(log2((_baseN - 1) / _baseD)) + 1".
        For small values of "baseN / baseD", this sometimes yields a bad upper-bound approximation.
        We therefore cover these cases (and a few more) manually.
        Complexity is O(log(input bit-length)).
    */
    function lnUpperBound32(uint256 _baseN, uint256 _baseD) constant returns (uint256) {
        assert(_baseN > _baseD);

        uint256 scaledBaseN = _baseN * 100000;
        if (scaledBaseN <= _baseD *  271828) // _baseN / _baseD < e^1 (floorLog2 will return 0 if _baseN / _baseD < 2)
            return uint256(1) << 32;
        if (scaledBaseN <= _baseD *  738905) // _baseN / _baseD < e^2 (floorLog2 will return 1 if _baseN / _baseD < 4)
            return uint256(2) << 32;
        if (scaledBaseN <= _baseD * 2008553) // _baseN / _baseD < e^3 (floorLog2 will return 2 if _baseN / _baseD < 8)
            return uint256(3) << 32;

        return (floorLog2((_baseN - 1) / _baseD) + 1) * 0xb17217f8;
    }

    /**
        input range:
            [0x100000000, uint256_max]
        output range:
            [0, 0x9b43d4f8d6]

        This method asserts outside of bounds

        Since `fixedLog2_min` output range is max `0xdfffffffff`
        (40 bits, or 5 bytes), we can use a very large approximation
        for `ln(2)`. This one is used since it's the max accuracy
        of Python `ln(2)`

        0xb17217f7d1cf78 = ln(2) * (1 << 56)
    */
    function fixedLoge(uint256 _x, uint8 _precision) constant returns (uint256) {
        // cannot represent negative numbers (below 1)
        assert(_x >= ONE << _precision);

        uint256 log2 = fixedLog2(_x, _precision);
        return (log2 * 0xb17217f7d1cf78) >> 56;
    }

    /**
        Returns log2(x >> 32) << 32 [1]
        So x is assumed to be already upshifted 32 bits, and
        the result is also upshifted 32 bits.

        [1] The function returns a number which is lower than the
        actual value

        input-range :
            [0x100000000, uint256_max]
        output-range:
            [0,0xdfffffffff]

        This method asserts outside of bounds

    */
    function fixedLog2(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 fixedOne = ONE << _precision;
        uint256 fixedTwo = TWO << _precision;

        // Numbers below 1 are negative.
        assert( _x >= fixedOne);

        uint256 hi = 0;
        while (_x >= fixedTwo) {
            _x >>= 1;
            hi += fixedOne;
        }

        for (uint8 i = 0; i < _precision; ++i) {
            _x = (_x * _x) / fixedOne;
            if (_x >= fixedTwo) {
                _x >>= 1;
                hi += ONE << (_precision - 1 - i);
            }
        }

        return hi;
    }

    /**
        floorLog2
        Takes a natural number (n) as input.
        Returns the largest integer smaller than or equal to the binary logarithm of the input.
        Complexity is O(log(input bit-length)).
    */
    function floorLog2(uint256 _n) constant returns (uint256) {
        uint8 t = 0;
        for (uint8 s = 128; s > 0; s >>= 1) {
            if (_n >= (ONE << s)) {
                _n >>= s;
                t |= s;
            }
        }

        return t;
    }

    /**
        fixedExp is a 'protected' version of `fixedExpUnsafe`, which asserts instead of overflows.
        The maximum value which can be passed to fixedExpUnsafe depends on the precision used.
        The following array maps each precision between 0 and 63 to the maximum value permitted:
        maxExpArray = {
            0xc1               ,0x17a              ,0x2e5              ,0x5ab              ,
            0xb1b              ,0x15bf             ,0x2a0c             ,0x50a2             ,
            0x9aa2             ,0x1288c            ,0x238b2            ,0x4429a            ,
            0x82b78            ,0xfaadc            ,0x1e0bb8           ,0x399e96           ,
            0x6e7f88           ,0xd3e7a3           ,0x1965fea          ,0x30b5057          ,
            0x5d681f3          ,0xb320d03          ,0x15784a40         ,0x292c5bdd         ,
            0x4ef57b9b         ,0x976bd995         ,0x122624e32        ,0x22ce03cd5        ,
            0x42beef808        ,0x7ffffffff        ,0xf577eded5        ,0x1d6bd8b2eb       ,
            0x386bfdba29       ,0x6c3390ecc8       ,0xcf8014760f       ,0x18ded91f0e7      ,
            0x2fb1d8fe082      ,0x5b771955b36      ,0xaf67a93bb50      ,0x15060c256cb2     ,
            0x285145f31ae5     ,0x4d5156639708     ,0x944620b0e70e     ,0x11c592761c666    ,
            0x2214d10d014ea    ,0x415bc6d6fb7dd    ,0x7d56e76777fc5    ,0xf05dc6b27edad    ,
            0x1ccf4b44bb4820   ,0x373fc456c53bb7   ,0x69f3d1c921891c   ,0xcb2ff529eb71e4   ,
            0x185a82b87b72e95  ,0x2eb40f9f620fda6  ,0x5990681d961a1ea  ,0xabc25204e02828d  ,
            0x14962dee9dc97640 ,0x277abdcdab07d5a7 ,0x4bb5ecca963d54ab ,0x9131271922eaa606 ,
            0x116701e6ab0cd188d,0x215f77c045fbe8856,0x3ffffffffffffffff,0x7abbf6f6abb9d087f,
        };
        Since we cannot use an array of constants, we need to approximate the maximum value dynamically.
        For a precision of 32, the maximum value permitted is MAX_FIXED_EXP_32.
        For each additional precision unit, the maximum value permitted increases by approximately 1.9.
        So in order to calculate it, we need to multiply MAX_FIXED_EXP_32 by 1.9 for every additional precision unit.
        And in order to optimize for speed, we multiply MAX_FIXED_EXP_32 by 1.9^2 for every 2 additional precision units.
        Hence the general function for mapping a given precision to the maximum value permitted is:
        - precision = [32, 34, 36, ..., 62]
        - MaxFixedExp(precision) = MAX_FIXED_EXP_32 * 3.61 ^ (precision / 2 - 16)
        Since we cannot use non-integers, we do MAX_FIXED_EXP_32 * 361 ^ (precision / 2 - 16) / 100 ^ (precision / 2 - 16).
        But there is a better approximation, because this "1.9" factor in fact extends beyond a single decimal digit.
        So instead, we use 0xeb5ec5975959c565 / 0x4000000000000000, which yields maximum values quite close to real ones:
        maxExpArray = {
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            -------------------,-------------------,-------------------,-------------------,
            0x386bfdba29       ,-------------------,0xcf8014760e       ,-------------------,
            0x2fb1d8fe07b      ,-------------------,0xaf67a93bb37      ,-------------------,
            0x285145f31a8f     ,-------------------,0x944620b0e5ee     ,-------------------,
            0x2214d10d0112e    ,-------------------,0x7d56e7677738e    ,-------------------,
            0x1ccf4b44bb20d0   ,-------------------,0x69f3d1c9210d27   ,-------------------,
            0x185a82b87b5b294  ,-------------------,0x5990681d95d4371  ,-------------------,
            0x14962dee9dbd672b ,-------------------,0x4bb5ecca961fb9bf ,-------------------,
            0x116701e6ab0967080,-------------------,0x3fffffffffffe6652,-------------------,
        };
    */
    function fixedExp(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 maxExp = MAX_FIXED_EXP_32;
        for (uint8 p = 32; p < _precision; p += 2)
            maxExp = (maxExp * 0xeb5ec5975959c565) >> (64-2);

        assert(_x <= maxExp);
        return fixedExpUnsafe(_x, _precision);
    }

    /**
        fixedExp
        Calculates e ^ x according to maclauren summation:

        e^x = 1 + x + x ^ 2 / 2!...+ x ^ n / n!

        and returns e ^ (x >> 32) << 32, that is, upshifted for accuracy

        Input range:
            - Function ok at    <= 242329958953
            - Function fails at >= 242329958954

        This method is is visible for testcases, but not meant for direct use.

        The values in this method been generated via the following python snippet:

        def calculateFactorials():
            """Method to print out the factorials for fixedExp"""

            ni = []
            ni.append(295232799039604140847618609643520000000) # 34!
            ITERATIONS = 34
            for n in range(1, ITERATIONS, 1) :
                ni.append(math.floor(ni[n - 1] / n))
            print( "\n        ".join(["xi = (xi * _x) >> _precision;\n        res += xi * %s;" % hex(int(x)) for x in ni]))

    */
    function fixedExpUnsafe(uint256 _x, uint8 _precision) constant returns (uint256) {
        uint256 xi = _x;
        uint256 res = uint256(0xde1bc4d19efcac82445da75b00000000) << _precision;

        res += xi * 0xde1bc4d19efcac82445da75b00000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x6f0de268cf7e5641222ed3ad80000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x2504a0cd9a7f7215b60f9be480000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9412833669fdc856d83e6f920000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1d9d4d714865f4de2b3fafea0000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x4ef8ce836bba8cfb1dff2a70000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xb481d807d1aa66d04490610000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x16903b00fa354cda08920c2000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x281cdaac677b334ab9e732000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x402e2aad725eb8778fd85000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x5d5a6c9f31fe2396a2af000000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x7c7890d442a82f73839400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9931ed54034526b58e400000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaf147cf24ce150cf7e00000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa200000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xbac08546b867cdaa20000;
        xi = (xi * _x) >> _precision;
        res += xi * 0xafc441338061b2820000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x9c3cabbc0056d790000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x839168328705c30000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x694120286c049c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x50319e98b3d2c000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x3a52a1e36b82000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x289286e0fce000;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1b0c59eb53400;
        xi = (xi * _x) >> _precision;
        res += xi * 0x114f95b55400;
        xi = (xi * _x) >> _precision;
        res += xi * 0xaa7210d200;
        xi = (xi * _x) >> _precision;
        res += xi * 0x650139600;
        xi = (xi * _x) >> _precision;
        res += xi * 0x39b78e80;
        xi = (xi * _x) >> _precision;
        res += xi * 0x1fd8080;
        xi = (xi * _x) >> _precision;
        res += xi * 0x10fbc0;
        xi = (xi * _x) >> _precision;
        res += xi * 0x8c40;
        xi = (xi * _x) >> _precision;
        res += xi * 0x462;
        xi = (xi * _x) >> _precision;
        res += xi * 0x22;

        return res / 0xde1bc4d19efcac82445da75b00000000;
    }
}


Updated comments, added acceptOwnership()

pragma solidity ^0.4.8;

// ----------------------------------------------------------------------------
// BokkyPooBah's Ether Refundable Prize
//
// A gift token backed by ethers. Designed to incentivise The DAO refund
// withdrawals, but can be used for any other purposes
//
// These tokens can be bought from this contract at the Buy Price.
//
// These tokens can be sold back to this contract at the Sell Price.
//
// Period                                ETH per BERP
// ------------------------- ------------------------
// From         To               Buy Price Sell Price
// ------------ ------------ ------------- ----------
// start        +7 days             0.0010     0.0010
// +7 days      +30 days            0.0011     0.0010
// +30 days     +60 days            0.0012     0.0010
// +60 days     +90 days            0.0013     0.0010
// +90 days     +365 days           0.0015     0.0010
// +365 days    forever          1000.0000     0.0010
//
// Based on Vlad's Safe Token Sale Mechanism Contract
// - https://medium.com/@Vlad_Zamfir/a-safe-token-sale-mechanism-8d73c430ddd1
//
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2017. The MIT Licence.
// ----------------------------------------------------------------------------

contract Owned {
    address public owner;
    address public newOwner;
    event OwnershipTransferred(address indexed _from, address indexed _to);

    function Owned() {
        owner = msg.sender;
    }

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

    function transferOwnership(address _newOwner) onlyOwner {
        newOwner = _newOwner;
    }

    function acceptOwnership() {
        if (msg.sender == newOwner) {
            OwnershipTransferred(owner, newOwner);
            owner = newOwner;
        }
    }
}

// ERC Token Standard #20 - https://github.com/ethereum/EIPs/issues/20
contract ERC20Token is Owned {
    uint256 _totalSupply = 0;

    // ------------------------------------------------------------------------
    // Balances for each account
    // ------------------------------------------------------------------------
    mapping(address => uint256) balances;

    // ------------------------------------------------------------------------
    // Owner of account approves the transfer of an amount to another account
    // ------------------------------------------------------------------------
    mapping(address => mapping (address => uint256)) allowed;

    // ------------------------------------------------------------------------
    // Get the total token supply
    // ------------------------------------------------------------------------
    function totalSupply() constant returns (uint256 totalSupply) {
        totalSupply = _totalSupply;
    }

    // ------------------------------------------------------------------------
    // Get the account balance of another account with address _owner
    // ------------------------------------------------------------------------
    function balanceOf(address _owner) constant returns (uint256 balance) {
        return balances[_owner];
    }

    // ------------------------------------------------------------------------
    // Transfer the balance from owner's account to another account
    // ------------------------------------------------------------------------
    function transfer(address _to, uint256 _amount) returns (bool success) {
        if (balances[msg.sender] >= _amount
            && _amount > 0
            && balances[_to] + _amount > balances[_to]) {
            balances[msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(msg.sender, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    // ------------------------------------------------------------------------
    // Allow _spender to withdraw from your account, multiple times, up to the
    // _value amount. If this function is called again it overwrites the
    // current allowance with _value.
    // ------------------------------------------------------------------------
    function approve(
        address _spender,
        uint256 _amount
    ) returns (bool success) {
        allowed[msg.sender][_spender] = _amount;
        Approval(msg.sender, _spender, _amount);
        return true;
    }

    // ------------------------------------------------------------------------
    // Spender of tokens transfer an amount of tokens from the token owner's
    // balance to the spender's account. The owner of the tokens must already
    // have approve(...)-d this transfer
    // ------------------------------------------------------------------------
    function transferFrom(
        address _from,
        address _to,
        uint256 _amount
    ) returns (bool success) {
        if (balances[_from] >= _amount
            && allowed[_from][msg.sender] >= _amount
            && _amount > 0
            && balances[_to] + _amount > balances[_to]) {
            balances[_from] -= _amount;
            allowed[_from][msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(_from, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    // ------------------------------------------------------------------------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // ------------------------------------------------------------------------
    function allowance(
        address _owner,
        address _spender
    ) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender,
        uint256 _value);
}

contract BokkyPooBahsEtherRefundablePrize is ERC20Token {

    // ------------------------------------------------------------------------
    // Token information
    // ------------------------------------------------------------------------
    string public constant symbol = "BERP";
    string public constant name = "BokkyPooBah´s Ether Refundable Prize";
    uint8 public constant decimals = 18;

    uint256 public deployedAt;

    function BokkyPooBahsEtherRefundablePrize() {
        deployedAt = now;
    }

    // ------------------------------------------------------------------------
    // Members buy tokens from this contract at this price
    //
    // This is a maximum price that the tokens should be bought at, as buyers
    // can always buy tokens from this contract for this price
    //
    // Check out the BERP prices on https://cryptoderivatives.market/ to see
    // if you can buy these tokens for less than this maximum price
    // ------------------------------------------------------------------------
    function buyPrice() constant returns (uint256) {
        return buyPriceAt(now);
    }

    function buyPriceAt(uint256 at) constant returns (uint256) {
        if (at < (deployedAt + 7 days)) {
            return 10 * 10**14;
        } else if (at < (deployedAt + 30 days)) {
            return 11 * 10**14;
        } else if (at < (deployedAt + 60 days)) {
            return 12 * 10**15;
        } else if (at < (deployedAt + 90 days)) {
            return 13 * 10**15;
        } else if (at < (deployedAt + 365 days)) {
            return 15 * 10**16;
        } else {
            return 10**21;
        }
    }

    // ------------------------------------------------------------------------
    // Members can always sell to the contract at 1 BERP = 0.001 ETH
    //
    // This is a minimum price that the tokens should sell for, as the owner of
    // the token can always sell tokens to this contract at this price
    //
    // Check out the BERP prices on https://cryptoderivatives.market/ to see
    // if you can sell these tokens for more than this minimum price
    // ------------------------------------------------------------------------
    function sellPrice() constant returns (uint256) {
        return 10**15;
    }

    // ------------------------------------------------------------------------
    // Buy tokens from the contract
    // ------------------------------------------------------------------------
    function () payable {
        buyTokens();
    }

    function buyTokens() payable {
        if (msg.value > 0) {
            uint tokens = msg.value * 1 ether / buyPrice();
            _totalSupply += tokens;
            balances[msg.sender] += tokens;
            TokensBought(msg.sender, msg.value, this.balance, tokens,
                 _totalSupply, buyPrice());
        }
    }
    event TokensBought(address indexed buyer, uint256 ethers,
        uint256 newEtherBalance, uint256 tokens, uint256 newTotalSupply,
        uint256 buyPrice);

    // ------------------------------------------------------------------------
    // Sell tokens to the contract
    // ------------------------------------------------------------------------
    function sellTokens(uint256 amountOfTokens) {
        if (amountOfTokens > balances[msg.sender]) throw;
        balances[msg.sender] -= amountOfTokens;
        _totalSupply -= amountOfTokens;
        uint256 ethersToSend = amountOfTokens * sellPrice() / 1 ether;
        if (!msg.sender.send(ethersToSend)) throw;
        TokensSold(msg.sender, ethersToSend, this.balance, amountOfTokens,
            _totalSupply, sellPrice());
    }
    event TokensSold(address indexed seller, uint256 ethers,
        uint256 newEtherBalance, uint256 tokens, uint256 newTotalSupply,
        uint256 sellPrice);

    // ------------------------------------------------------------------------
    // Receive deposits. This could be a free donation, or fees earned by
    // a system of payments backing this contract
    // ------------------------------------------------------------------------
    function deposit() payable {
        Deposited(msg.value, this.balance);
    }
    event Deposited(uint256 amount, uint256 balance);

    // ------------------------------------------------------------------------
    // Owner Withdrawal
    // ------------------------------------------------------------------------
    function ownerWithdraw(uint256 amount) onlyOwner {
        uint256 maxWithdrawalAmount = amountOfEthersOwnerCanWithdraw();
        if (amount > maxWithdrawalAmount) {
            amount = maxWithdrawalAmount;
        }
        if (!owner.send(amount)) throw;
        Withdrawn(amount, maxWithdrawalAmount - amount);
    }
    event Withdrawn(uint256 amount, uint256 remainingWithdrawal);

    // ------------------------------------------------------------------------
    // Amount the owner can withdraw
    // ------------------------------------------------------------------------
    function amountOfEthersOwnerCanWithdraw() constant returns (uint256) {
        uint256 etherBalance = this.balance;
        uint256 ethersSupportingTokens = _totalSupply * sellPrice() / 1 ether;
        if (etherBalance > ethersSupportingTokens) {
            return etherBalance - ethersSupportingTokens;
        } else {
            return 0;
        }
    }

    // ------------------------------------------------------------------------
    // Information function
    // ------------------------------------------------------------------------
    function currentEtherBalance() constant returns (uint256) {
        return this.balance;
    }

    function currentTokenBalance() constant returns (uint256) {
        return _totalSupply;
    }
}

pragma solidity ^0.4.8;

// ----------------------------------------------------------------------------
// BokkyPooBah's Ether Refundable Prize
//
// A gift token backed by ethers. Designed to incentivise The DAO refund
// withdrawals, but can be used for any other purposes
//
// These tokens can be bought from this contract at the Buy Price.
//
// These tokens can be sold back to this contract at the Sell Price.
//
// Period                                ETH per BERP
// ------------------------- ------------------------
// From         To               Buy Price Sell Price
// ------------ ------------ ------------- ----------
// start        +7 days             0.0010     0.0010
// +7 days      +30 days            0.0011     0.0010
// +30 days     +60 days            0.0012     0.0010
// +60 days     +90 days            0.0013     0.0010
// +90 days     +365 days           0.0015     0.0010
// +365 days    forever          1000.0000     0.0010
//
// Based on Vlad's Safe Token Sale Mechanism Contract
// - https://medium.com/@Vlad_Zamfir/a-safe-token-sale-mechanism-8d73c430ddd1
//
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2017. The MIT Licence.
// ----------------------------------------------------------------------------

contract Owned {
    address public owner;
    event OwnershipTransferred(address indexed _from, address indexed _to);

    function Owned() {
        owner = msg.sender;
    }

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

    function transferOwnership(address newOwner) onlyOwner {
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

// ERC Token Standard #20 - https://github.com/ethereum/EIPs/issues/20
contract ERC20Token is Owned {
    uint256 _totalSupply = 0;

    // Balances for each account
    mapping(address => uint256) balances;

    // Owner of account approves the transfer of an amount to another account
    mapping(address => mapping (address => uint256)) allowed;

    // Get the total token supply
    function totalSupply() constant returns (uint256 totalSupply) {
        totalSupply = _totalSupply;
    }

    // Get the account balance of another account with address _owner
    function balanceOf(address _owner) constant returns (uint256 balance) {
        return balances[_owner];
    }

    // Send _value amount of tokens to address _to
    function transfer(address _to, uint256 _amount) returns (bool success) {
        if (balances[msg.sender] >= _amount
            && _amount > 0
            && balances[_to] + _amount > balances[_to]) {
            balances[msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(msg.sender, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    // Allow _spender to withdraw from your account, multiple times, up to the
    // _value amount. If this function is called again it overwrites the
    // current allowance with _value.
    function approve(
        address _spender,
        uint256 _amount
    ) returns (bool success) {
        allowed[msg.sender][_spender] = _amount;
        Approval(msg.sender, _spender, _amount);
        return true;
    }

    // Spender of tokens transfer an amount of tokens from the token owner's
    // balance to the spender's account. The owner of the tokens must already
    // have approve(...)-d this transfer
    function transferFrom(
        address _from,
        address _to,
        uint256 _amount
    ) returns (bool success) {
        if (balances[_from] >= _amount
            && allowed[_from][msg.sender] >= _amount
            && _amount > 0
            && balances[_to] + _amount > balances[_to]) {
            balances[_from] -= _amount;
            allowed[_from][msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(_from, _to, _amount);
            return true;
        } else {
            return false;
        }
    }

    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    function allowance(
        address _owner,
        address _spender
    ) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender,
        uint256 _value);
}

contract BokkyPooBahsEtherRefundablePrize is ERC20Token {

    // ------------------------------------------------------------------------
    // Token information
    // ------------------------------------------------------------------------
    string public constant symbol = "BERP";
    string public constant name = "BokkyPooBah´s Ether Refundable Prize";
    uint8 public constant decimals = 18;

    uint256 public deployedAt;

    function BokkyPooBahsEtherRefundablePrize() {
        deployedAt = now;
    }

    // ------------------------------------------------------------------------
    // Members buy tokens from this contract at this price
    //
    // This is a maximum price that the tokens should be bought at, as buyers
    // can always buy tokens from this contract for this price
    //
    // Check out the BERP prices on https://cryptoderivatives.market/ to see
    // if you can buy these tokens for less than this maximum price
    // ------------------------------------------------------------------------
    function buyPrice() constant returns (uint256) {
        return buyPriceAt(now);
    }

    function buyPriceAt(uint256 at) constant returns (uint256) {
        if (at < (deployedAt + 7 days)) {
            return 10 * 10**14;
        } else if (at < (deployedAt + 30 days)) {
            return 11 * 10**14;
        } else if (at < (deployedAt + 60 days)) {
            return 12 * 10**15;
        } else if (at < (deployedAt + 90 days)) {
            return 13 * 10**15;
        } else if (at < (deployedAt + 365 days)) {
            return 15 * 10**16;
        } else {
            return 10**21;
        }
    }

    // ------------------------------------------------------------------------
    // Members can always sell to the contract at 1 BERP = 0.001 ETH
    //
    // This is a minimum price that the tokens should sell for, as the owner of
    // the token can always sell tokens to this contract at this price
    //
    // Check out the BERP prices on https://cryptoderivatives.market/ to see
    // if you can sell these tokens for more than this minimum price
    // ------------------------------------------------------------------------
    function sellPrice() constant returns (uint256) {
        return 10**15;
    }

    // ------------------------------------------------------------------------
    // Buy tokens from the contract
    // ------------------------------------------------------------------------
    function () payable {
        buyTokens();
    }

    function buyTokens() payable {
        if (msg.value > 0) {
            uint tokens = msg.value * 1 ether / buyPrice();
            _totalSupply += tokens;
            balances[msg.sender] += tokens;
            TokensBought(msg.sender, msg.value, this.balance, tokens,
                 _totalSupply, buyPrice());
        }
    }
    event TokensBought(address indexed buyer, uint256 ethers,
        uint256 newEtherBalance, uint256 tokens, uint256 newTotalSupply,
        uint256 buyPrice);

    // ------------------------------------------------------------------------
    // Sell tokens to the contract
    // ------------------------------------------------------------------------
    function sellTokens(uint256 amountOfTokens) {
        if (amountOfTokens > balances[msg.sender]) throw;
        balances[msg.sender] -= amountOfTokens;
        _totalSupply -= amountOfTokens;
        uint256 ethersToSend = amountOfTokens * sellPrice() / 1 ether;
        if (!msg.sender.send(ethersToSend)) throw;
        TokensSold(msg.sender, ethersToSend, this.balance, amountOfTokens,
            _totalSupply, sellPrice());
    }
    event TokensSold(address indexed seller, uint256 ethers,
        uint256 newEtherBalance, uint256 tokens, uint256 newTotalSupply,
        uint256 sellPrice);

    // ------------------------------------------------------------------------
    // Receive deposits. This could be a free donation, or fees earned by
    // a system of payments backing this contract
    // ------------------------------------------------------------------------
    function deposit() payable {
        Deposited(msg.value, this.balance);
    }
    event Deposited(uint256 amount, uint256 balance);

    // ------------------------------------------------------------------------
    // Owner Withdrawal
    // ------------------------------------------------------------------------
    function ownerWithdraw(uint256 amount) onlyOwner {
        uint256 maxWithdrawalAmount = amountOfEthersOwnerCanWithdraw();
        if (amount > maxWithdrawalAmount) {
            amount = maxWithdrawalAmount;
        }
        if (!owner.send(amount)) throw;
        Withdrawn(amount, maxWithdrawalAmount - amount);
    }
    event Withdrawn(uint256 amount, uint256 remainingWithdrawal);

    // ------------------------------------------------------------------------
    // Information function
    // ------------------------------------------------------------------------
    function amountOfEthersOwnerCanWithdraw() constant returns (uint256) {
        uint256 etherBalance = this.balance;
        uint256 ethersSupportingTokens = _totalSupply * sellPrice() / 1 ether;
        if (etherBalance > ethersSupportingTokens) {
            return etherBalance - ethersSupportingTokens;
        } else {
            return 0;
        }
    }

    function currentEtherBalance() constant returns (uint256) {
        return this.balance;
    }

    function currentTokenBalance() constant returns (uint256) {
        return _totalSupply;
    }
}


test: refactor and cleanup

test: refactor and cleanup

pragma solidity ^0.8.9;

import "ds-test/test.sol";
import "contracts/governance/Governor.sol";
import "contracts/Controller.sol";
import "contracts/bonding/BondingManager.sol";
import "contracts/snapshots/MerkleSnapshot.sol";

interface CheatCodes {
    function roll(uint256) external;

    function prank(address) external;

    function expectRevert(bytes calldata) external;

    function expectEmit(
        bool checkTopic1,
        bool checkTopic2,
        bool checkTopic3,
        bool checkData
    ) external;

    function mockCall(
        address,
        bytes calldata,
        bytes calldata
    ) external;
}

interface L2Migrator {
    function claimStake(
        address,
        uint256,
        uint256,
        bytes32[] calldata,
        address
    ) external;
}

// forge test --match-contract BondingManagerForceChangeDelegateFix --fork-url https://arbitrum-mainnet.infura.io/v3/<INFURA_KEY> -vvv --fork-block-number 8006620
contract BondingManagerForceChangeDelegateFix is DSTest {
    CheatCodes public constant CHEATS = CheatCodes(HEVM_ADDRESS);

    Governor public constant GOVERNOR = Governor(0xD9dEd6f9959176F0A04dcf88a0d2306178A736a6);
    Controller public constant CONTROLLER = Controller(0xD8E8328501E9645d16Cf49539efC04f734606ee4);
    BondingManager public constant BONDING_MANAGER = BondingManager(0x35Bcf3c30594191d53231E4FF333E8A770453e40);
    MerkleSnapshot public constant MERKLE_SNAPSHOT = MerkleSnapshot(0x10736ffaCe687658F88a46D042631d182C7757f7);
    L2Migrator public constant L2_MIGRATOR = L2Migrator(0x148D5b6B4df9530c7C76A810bd1Cdf69EC4c2085);

    address public constant GOVERNOR_OWNER = 0x04F53A0bb244f015cC97731570BeD26F0229da05;

    bytes32 public constant BONDING_MANAGER_TARGET_ID = keccak256("BondingManagerTarget");

    // Governor update
    address[] public targets;
    uint256[] public values;
    bytes[] public datas;
    bytes20 public gitCommitHash;

    BondingManager public newBondingManagerTarget;

    event Bond(
        address indexed newDelegate,
        address indexed oldDelegate,
        address indexed delegator,
        uint256 additionalAmount,
        uint256 bondedAmount
    );

    function setUp() public {
        newBondingManagerTarget = new BondingManager(address(CONTROLLER));

        targets = [address(CONTROLLER)];
        values = [0];

        (, gitCommitHash) = CONTROLLER.getContractInfo(BONDING_MANAGER_TARGET_ID);
        datas = [
            abi.encodeWithSelector(
                CONTROLLER.setContractInfo.selector,
                BONDING_MANAGER_TARGET_ID,
                address(newBondingManagerTarget),
                gitCommitHash
            )
        ];

        uint256 round = 2499;
        uint256 blockNum = round * 5760;
        CHEATS.roll(blockNum);

        upgradeBondingManager();
    }

    function upgradeBondingManager() public {
        Governor.Update memory update = Governor.Update({ target: targets, value: values, data: datas, nonce: 0 });

        // Impersonate Governor owner
        CHEATS.prank(GOVERNOR_OWNER);
        GOVERNOR.stage(update, 0);
        GOVERNOR.execute(update);
    }

    function testUpgrade() public {
        (, bytes20 gitCommitHash) = CONTROLLER.getContractInfo(BONDING_MANAGER_TARGET_ID);

        // Check that new BondingManagerTarget is registered
        (address infoAddr, bytes20 infoGitCommitHash) = CONTROLLER.getContractInfo(BONDING_MANAGER_TARGET_ID);
        assertEq(infoAddr, address(newBondingManagerTarget));
        assertEq(infoGitCommitHash, gitCommitHash);
    }

    function testBond() public {
        address delegator = 0x5Ec2be1aDC70Bc338471277c2dCc183b0b2C91be;
        (, , address delegateAddress, , , , ) = BONDING_MANAGER.getDelegator(delegator);

        uint256 initialStake = BONDING_MANAGER.transcoderTotalStake(delegateAddress);

        CHEATS.prank(delegator);
        BONDING_MANAGER.bond(10, delegateAddress);

        uint256 finalStake = BONDING_MANAGER.transcoderTotalStake(delegateAddress);

        assertEq(finalStake, initialStake + 10);
    }

    function testChangeDelegate() public {
        address delegator = 0xAcA4bD77e459b9898A0de9Ad7C1caC34fF540D0B;
        address delegate = 0x525419FF5707190389bfb5C87c375D710F5fCb0E;

        // checks if owner can change delegate
        CHEATS.prank(delegator);
        BONDING_MANAGER.bond(0, delegate);

        (, , address delegateAddress, , , , ) = BONDING_MANAGER.getDelegator(delegator);

        assertEq(delegateAddress, delegate);
    }

    function testClaimStake() public {
        CHEATS.mockCall(
            address(MERKLE_SNAPSHOT),
            abi.encodeWithSelector(MERKLE_SNAPSHOT.verify.selector),
            abi.encode(true)
        );

        address delegator = 0xE22d48950C88C4e8F2C5dA6c7d32D4bc9fE43Bff;
        address delegate = 0x91f19C0335BC776f4693EeB1D88765243f63e9D6;

        bytes32[] memory proof;
        CHEATS.prank(delegator);

        CHEATS.expectEmit(true, true, true, true);
        emit Bond(delegate, address(0), delegator, 500000000000000000000, 500000000000000000000);
        L2_MIGRATOR.claimStake(delegate, 500000000000000000000, 0, proof, address(0));

        (, , address delegateAddress, , , , ) = BONDING_MANAGER.getDelegator(delegator);

        assertEq(delegateAddress, delegate);
    }

    function testChangeDelegateByThirdParty() public {
        address delegator = 0xAcA4bD77e459b9898A0de9Ad7C1caC34fF540D0B;
        address delegate = 0x525419FF5707190389bfb5C87c375D710F5fCb0E;
        address thirdParty = 0x12336b564A71Cc4C1319bf35E87Ea45681E4D94a;

        // trying to change delegate of a delegator should revert
        CHEATS.prank(thirdParty);
        CHEATS.expectRevert(bytes("INVALID_CALLER"));
        BONDING_MANAGER.bondForWithHint(0, delegator, delegate, address(0), address(0), address(0), address(0));
    }
}

pragma solidity ^0.8.9;

import "ds-test/test.sol";
import "contracts/governance/Governor.sol";
import "contracts/Controller.sol";
import "contracts/bonding/BondingManager.sol";
import "contracts/snapshots/MerkleSnapshot.sol";

interface CheatCodes {
    function roll(uint256) external;

    function prank(address) external;

    function expectRevert(bytes calldata) external;

    function expectEmit(
        bool checkTopic1,
        bool checkTopic2,
        bool checkTopic3,
        bool checkData
    ) external;

    function mockCall(
        address,
        bytes calldata,
        bytes calldata
    ) external;
}

interface L2Migrator {
    function claimStake(
        address,
        uint256,
        uint256,
        bytes32[] calldata,
        address
    ) external;
}

// forge test --match-contract BondingManagerForceChangeDelegateFix --fork-url https://arbitrum-mainnet.infura.io/v3/<INFURA_KEY> -vvv --fork-block-number 8006620
contract BondingManagerForceChangeDelegateFix is DSTest {
    CheatCodes public constant CHEATS = CheatCodes(HEVM_ADDRESS);

    Governor public constant GOVERNOR = Governor(0xD9dEd6f9959176F0A04dcf88a0d2306178A736a6);
    Controller public constant CONTROLLER = Controller(0xD8E8328501E9645d16Cf49539efC04f734606ee4);
    BondingManager public constant BONDING_MANAGER = BondingManager(0x35Bcf3c30594191d53231E4FF333E8A770453e40);
    MerkleSnapshot public constant MERKLE_SNAPSHOT = MerkleSnapshot(0x10736ffaCe687658F88a46D042631d182C7757f7);
    L2Migrator public constant L2_MIGRATOR = L2Migrator(0x148D5b6B4df9530c7C76A810bd1Cdf69EC4c2085);

    address public constant GOVERNOR_OWNER = 0x04F53A0bb244f015cC97731570BeD26F0229da05;

    bytes32 public constant BONDING_MANAGER_TARGET_ID = keccak256("BondingManagerTarget");

    // Governor update
    address[] public targets;
    uint256[] public values;
    bytes[] public datas;

    BondingManager public newBondingManagerTarget;

    event Bond(
        address indexed newDelegate,
        address indexed oldDelegate,
        address indexed delegator,
        uint256 additionalAmount,
        uint256 bondedAmount
    );

    function setUp() public {
        newBondingManagerTarget = new BondingManager(address(CONTROLLER));

        targets = [address(CONTROLLER)];
        values = [0];

        (, bytes20 gitCommitHash) = CONTROLLER.getContractInfo(BONDING_MANAGER_TARGET_ID);
        datas = [
            abi.encodeWithSelector(
                CONTROLLER.setContractInfo.selector,
                BONDING_MANAGER_TARGET_ID,
                address(newBondingManagerTarget),
                gitCommitHash
            )
        ];
    }

    function upgradeBondingManager() public {
        Governor.Update memory update = Governor.Update({ target: targets, value: values, data: datas, nonce: 0 });

        // Impersonate Governor owner
        CHEATS.prank(GOVERNOR_OWNER);
        GOVERNOR.stage(update, 0);
        GOVERNOR.execute(update);
    }

    function testUpgrade() public {
        (, bytes20 gitCommitHash) = CONTROLLER.getContractInfo(BONDING_MANAGER_TARGET_ID);

        upgradeBondingManager();

        // Check that new BondingManagerTarget is registered
        (address infoAddr, bytes20 infoGitCommitHash) = CONTROLLER.getContractInfo(BONDING_MANAGER_TARGET_ID);
        assertEq(infoAddr, address(newBondingManagerTarget));
        assertEq(infoGitCommitHash, gitCommitHash);
    }

    function testBond() public {
        upgradeBondingManager();

        uint256 round = 2499;
        uint256 blockNum = round * 5760;
        CHEATS.roll(blockNum);

        address delegator = 0x5Ec2be1aDC70Bc338471277c2dCc183b0b2C91be;
        (, , address delegateAddress, , , , ) = BONDING_MANAGER.getDelegator(delegator);

        uint256 initialStake = BONDING_MANAGER.transcoderTotalStake(delegateAddress);

        CHEATS.prank(delegator);
        BONDING_MANAGER.bond(10, delegateAddress);

        uint256 finalStake = BONDING_MANAGER.transcoderTotalStake(delegateAddress);

        assertEq(finalStake, initialStake + 10);
    }

    function testChangeDelegate() public {
        upgradeBondingManager();

        uint256 round = 2499;
        uint256 blockNum = round * 5760;
        CHEATS.roll(blockNum);

        address delegator = 0xAcA4bD77e459b9898A0de9Ad7C1caC34fF540D0B;
        address delegate = 0x525419FF5707190389bfb5C87c375D710F5fCb0E;

        // checks if owner can change delegate
        CHEATS.prank(delegator);
        BONDING_MANAGER.bond(0, delegate);

        (, , address delegateAddress, , , , ) = BONDING_MANAGER.getDelegator(delegator);

        assertEq(delegateAddress, delegate);
    }

    function testClaimStake() public {
        upgradeBondingManager();

        CHEATS.mockCall(
            address(MERKLE_SNAPSHOT),
            abi.encodeWithSelector(MERKLE_SNAPSHOT.verify.selector),
            abi.encode(true)
        );

        uint256 round = 2499;
        uint256 blockNum = round * 5760;
        CHEATS.roll(blockNum);

        address delegator = 0xE22d48950C88C4e8F2C5dA6c7d32D4bc9fE43Bff;
        address delegate = 0x91f19C0335BC776f4693EeB1D88765243f63e9D6;

        bytes32[] memory proof;
        CHEATS.prank(delegator);

        CHEATS.expectEmit(true, true, false, true);
        emit Bond(delegate, address(0), delegator, 500000000000000000000, 500000000000000000000);
        L2_MIGRATOR.claimStake(delegate, 500000000000000000000, 0, proof, address(0));

        (, , address delegateAddress, , , , ) = BONDING_MANAGER.getDelegator(delegator);

        assertEq(delegateAddress, delegate);
    }

    function testChangeDelegateByThirdParty() public {
        upgradeBondingManager();

        uint256 round = 2499;
        uint256 blockNum = round * 5760;
        CHEATS.roll(blockNum);

        address delegator = 0xAcA4bD77e459b9898A0de9Ad7C1caC34fF540D0B;
        address delegate = 0x525419FF5707190389bfb5C87c375D710F5fCb0E;
        address thirdParty = 0x12336b564A71Cc4C1319bf35E87Ea45681E4D94a;

        // trying to change delegate of a delegator should revert
        CHEATS.prank(thirdParty);
        CHEATS.expectRevert(bytes("INVALID_CALLER"));
        BONDING_MANAGER.bondForWithHint(0, delegator, delegate, address(0), address(0), address(0), address(0));
    }
}


Syntax fixup

Syntax fixup

import 'token/Token.sol';
import './AddressList.sol';

/**
 * @dev The library for voting actions.
 *      This data contains stack of voters, its opinion and count of shares.
 */
library Voting {
    /* Voting structure */
    struct Poll {
        /* Stack of all voters */
        AddressList.Data            voters;
        /* Stack of all variants by value */
        AddressList.Data            poll;
        /* Count of shares for given variant */
        mapping(address => uint)    valueOf;
        /* Count of shares for given voter */
        mapping(address => uint)    shareOf;
        /* Poll variant for given voter */
        mapping(address => address) pollOf;
    }

    using AddressList for AddressList.Data;

    /**
     * @dev Current high value poll
     * @param _poll ref to `Poll` structure
     * @return current value
     */
    function current(Poll storage _poll) constant returns (address)
    { return _poll.poll.first(); }

    /**
     * @dev Increase poll shares for given variant
     * @param _poll ref to `Poll` structure
     * @param _variant voter variant value
     * @param _shares token represents vote
     * @param _count how much votes are given
     */
    function up(Poll storage _poll, address _voter, address _variant,
                Token _shares, uint _count) {
        // Try to transfer count of shares from voter to self
        if (!_shares.transferFrom(_voter, this, _count))
            throw;

        // Increase shares and set the poll
        _poll.shareOf[_voter]   += _count;
        _poll.pollOf[_voter]     = _variant;
        _poll.valueOf[_variant] += _count;

        // Append voter if not in list
        if (!_poll.voters.contains(_voter))
            _poll.voters.append(_voter);

        // Append variant if not in list
        if (!_poll.poll.contains(_variant))
            _poll.poll.append(_variant);

        // Shift voter in the stack
        shiftLeft(_poll, _variant);
    }

    /**
     * @dev Decrease poll shares of given voter
     * @param _poll ref to `Poll` structure
     * @param _count how much shares will decreased
     */
    function down(Poll storage _poll, address _voter, Token _shares, uint _count) {
        // So I can refund no more that gives from voter
        var refund = _poll.shareOf[_voter] > _count ? _count : _poll.shareOf[_voter];

        // Transfer shares
        _shares.transfer(_voter, refund);
        _poll.shareOf[_voter]               -= refund;
        _poll.valueOf[_poll.pollOf[_voter]] -= refund;

        // Shift right or drop when no shares
        if (_poll.shareOf[_voter] > 0) {
            shiftRight(_poll, _poll.pollOf[_voter]);
        } else {
            _poll.voters.remove(_voter);
        }
    }

    /*
     * Shifting mechanism
     * Thesys: the stack of variants should be sorted by valueOf value.
     * Solution:
     *  - `up` call: variant shifted left while his valueOf value is large
     *  - `down` call: varian shifted right in the stack while valueOf value is low
     */

    function shiftLeft(Poll storage _poll, address _variant) internal {
        var value = _poll.valueOf[_variant];
        var left  = _poll.poll.prev(_variant);

        while (left != 0 && _poll.valueOf[left] < value) {
            _poll.poll.swap(left, _variant);
            left = _poll.poll.prev(_variant);
        }
    }

    function shiftRight(Poll storage _poll, address _variant) internal {
        var value = _poll.valueOf[_variant];
        var right = _poll.poll.next(_variant);

        while (right != 0 && _poll.valueOf[right] > value) {
            _poll.poll.swap(right, _variant);
            right = _poll.poll.next(_variant);
        }
    }
}

import 'token/Token.sol';
import './AddressList.sol';

/**
 * @dev The library for voting actions.
 *      This data contains stack of voters, its opinion and count of shares.
 */
library Voting {
    /* Voting structure */
    struct Poll {
        /* Stack of all voters */
        AddressList.Data            voters;
        /* Stack of all variants by value */
        AddressList.Data            poll;
        /* Count of shares for given variant */
        mapping(address => uint)    valueOf;
        /* Count of shares for given voter */
        mapping(address => uint)    shareOf;
        /* Poll variant for given voter */
        mapping(address => address) pollOf;
    }

    using AddressList for AddressList.Data;

    /**
     * @dev Current high value poll
     * @param _poll ref to `Poll` structure
     * @return current value
     */
    function current(Poll storage _poll) constant returns (address)
    { return _poll.poll.first(); }

    /**
     * @dev Increase poll shares for given variant
     * @param _poll ref to `Poll` structure
     * @param _variant voter variant value
     * @param _shares token represents vote
     * @param _count how much votes are given
     */
    function up(Poll storage _poll, address _voter, address _variant,
                Token _shares, uint _count) {
        // Try to transfer count of shares from voter to self
        if (!_shares.transferFrom(_voter, this, _count))
            throw;

        // Increase shares and set the poll
        _poll.shareOf[_voter]   += _count;
        _poll.pollOf[_voter]     = _variant;
        _poll.valueOf[_variant] += _count;

        // Append voter if not in list
        if (!_poll.voters.contains(_voter))
            _poll.voters.append(_voter);

        // Append variant if not in list
        if (!_poll.poll.contains(_variant))
            _poll.poll.append(_variant);

        // Shift voter in the stack
        shiftLeft(_poll, _variant);
    }

    /**
     * @dev Decrease poll shares of given voter
     * @param _poll ref to `Poll` structure
     * @param _count how much shares will decreased
     */
    function down(Poll storage _poll, address _voter, Token _shares, uint _count) {
        // So I can refund no more that gives from voter
        var refund = _poll.shareOf[_voter] > _count ? _count : _poll.shareOf[_voter];

        // Transfer shares
        _shares.transfer(_voter, refund);
        _poll.shareOf[_voter]               -= refund;
        _poll.valueOf[_poll.pollOf[_voter]] -= refund;

        // Shift right or drop when no shares
        if (_poll.shareOf[_voter] > 0) {
            shiftRight(_poll, _poll.pollOf[_voter]);
        } else {
            _poll.voters.remove(_voter);
        }
    }

    /*
     * Shifting mechanism
     * Thesys: the stack of variants should be sorted by valueOf value.
     * Solution:
     *  - `up` call: variant shifted left while his valueOf value is large
     *  - `down` call: varian shifted right in the stack while valueOf value is low
     */

    function shiftLeft(Poll storage _poll, address _variant) internal {
        var value = _poll.valueOf[_variant];
        var left  = _poll.poll.prev(_variant);

        while (left != 0 && _poll.valueOf[left] < value) {
            _poll.poll.swap(left, _voter);
            left = _poll.poll.prev(_variant);
        }
    }

    function shiftRight(Poll storage _poll, address _variant) internal {
        var value = _poll.valueOf[_variant];
        var right = _poll.poll.next(_variant);

        while (right != 0 && _poll.valueOf[right] > value) {
            _poll.poll.swap(right, _variant);
            right = _poll.poll.next(_variant);
        }
    }
}