contract PausableCompoundInterestERC20 is Pausable, BurnerAccount, InterestRateBased, ERC20Token {
    // Non EIP20 Standard Constants, Variables and Events
    event Mint(address indexed to, uint256 tokens);
    event Burn(uint256 tokens);
    event InterestRateChange(uint256 intervalDuration, uint256 intervalExpiry, uint256 indexed interestRateIndex);
    event InterestClaimed(address indexed tokenOwner, uint256 amountOwed);

    // the interest pool account address, that wont be included in total supply
    // hex generated with linux system entropy + dice + keys (private key thrown out)
    address public constant interestPool = address(0xd365131390302b58A61E265744288097Bd53532e);

    // this is the based supply pool address, which is used to calculate total supply with interest accured
    // hex generated with linux system entropy + dice + keys (private key thrown out)
    address public constant supplyPool = address(0x85c05851ef3175aeFBC74EcA16F174E22b5acF28);

    // is not a pool account
    modifier isNotPool(address tokenOwner) {
        assert(tokenOwner != supplyPool && tokenOwner != interestPool); _;
    }

    // total supply with amount owed
    function totalSupply() external view returns (uint256 supplyWithAccruedInterest) {
        (uint256 amountOwed,,) = interestOwed(supplyPool);

        return add(balanceOf(supplyPool), amountOwed);
    }

    // Dai/Maker style minting
    function mint(address to, uint256 amount) public isOwner pausable isNotPool(to) {
        // any time the supply pool changes, we need to update it's interest owed
        claimInterestOwed(supplyPool);

        balances[supplyPool] = add(balances[supplyPool], amount);
        balances[to] = add(balances[to], amount);

        recordBalance(supplyPool);
        recordBalance(to);

        emit Mint(to, amount);
    }

    // the burner can only burn tokens in the burn account
    function burn(address account) external isOwnerOrBurner pausable isNotPool(account) {
        // target burn address
        address target = msg.sender == burner ? burner : account;

        // any time the supply pool changes, we need to update it's interest owed
        claimInterestOwed(supplyPool);

        emit Burn(balances[target]);

        balances[supplyPool] = sub(balances[supplyPool], balances[target]);
        balances[target] = 0;

        // technially the burner account can claim interest, not that it should matter
        recordBalance(supplyPool);
        recordBalance(target);
    }

    // change interest rates
    function changeInterestRate(
        uint256 duration,
        uint256 maximum,
        uint256 interestRate,
        uint256 increasePool,
        uint256 decreasePool) public isOwner pausable {
        // claim up supply pool amount
        if (interestRates.length > 0) {
          claimInterestOwed(supplyPool); }

        // set duration and maximum
        changeDuration(duration);

        // set interval maximum
        intervalMaximum = maximum;

        // record interest rate..
        recordInterestRate(interestRate);

        // set interest pool, no balance needs to be recorded here as this is the interest pool
        balances[interestPool] = sub(add(balances[interestPool], increasePool),
          decreasePool);
    }

    // hard token set for interest pool
    function setInterestPool(uint256 tokens) external isOwner pausable {
        balances[interestPool] = tokens;
        // no need to record balance as this is the interest pool account..
    }

    // claim interest owed
    function claimInterestOwed(address tokenOwner) public pausable {
        // cant claim interest on the interest pool
        assert(tokenOwner != interestPool);

        // calculate interest balances and new record indexes
        (uint256 amountOwed, uint256 balanceIndex, uint256 interval) = interestOwed(tokenOwner);

        // set last balance index used (it's always one ahead so subtract one)
        lastClaimedBalanceIndex[tokenOwner] = balanceIndex;

        // set interval offset
        if (balanceRecords[tokenOwner].length > 0) {
          balanceRecords[tokenOwner][balanceIndex].intervalOffset = interval;
        }

        // increase the balance of the account, reduce interest pool
        if (tokenOwner != supplyPool) {
          balances[interestPool] = sub(balances[interestPool], amountOwed);
        }

        // set new token owner balance, record balance event
        balances[tokenOwner] = add(balances[tokenOwner], amountOwed);
        recordBalance(tokenOwner);

        // fire the interest claimed event
        emit InterestClaimed(tokenOwner, amountOwed);
    }

    function transferFrom(address from, address to, uint256 tokens) public pausable isNotPool(from) isNotPool(to) returns (bool success) {
        super.transferFrom(from, to, tokens);

        recordBalance(from);
        recordBalance(to);

        return true;
    }

    // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount.
    // If this function is called again it overwrites the current allowance with _value.
    function approve(address spender, uint256 tokens) public pausable isNotPool(spender) returns (bool success) {
        return super.approve(spender, tokens);
    }
}
/**
 * @title PausableCompoundInterestERC20
 * @author UnityCoin Team
 * @notice An implimentation of a mintable, pausable, burnable, compound interest based
 *       ERC20 token.
 *
 *       The token has a few *special* properties.
 *         - a special burner account (which can burn tokens in its account)
 *         - a special supply tracking pool account / mechanism
 *         - a special interest pool account which interest payments are drawn from
 *         - you cannot transfer from / to any pool (supply or interest)
 *         - you cannot claim interest on the interest pool account
 *         - by all accounts the interest and supply accounts dont really exist
 *           and are used for internal accounting purposes.
 *
 *       Minting / burning / pausing style is based roughly on DSToken from maker.
 *
 *       Whenever we burn, mint, change rates we update the supply pool,
 *       which intern updates the totalSupply return.
 *
 *       The TotalSupply of this token should be as follows:
 *       total supply = supply issued + total interest accued up to current interval
 *
 *       The special `burner` account can only burn tokens sent to it's account.
 *       You can think of it as a HOT burn account.
 *       The provider can ultimatly burn any account.
 */
function burn(address account) external isOwnerOrBurner pausable isNotPool(account) {
    // target burn address
    address target = msg.sender == burner ? burner : account;

    // any time the supply pool changes, we need to update it's interest owed
    claimInterestOwed(supplyPool);

    emit Burn(balances[target]);

    balances[supplyPool] = sub(balances[supplyPool], balances[target]);
    balances[target] = 0;

    // technially the burner account can claim interest, not that it should matter
    recordBalance(supplyPool);
    recordBalance(target);
}

// the burner can only burn tokens in the burn account