fix bonus awarding

fix bonus awarding

import "libraries/GroveLib.sol";
import "libraries/ResourcePoolLib.sol";
import "libraries/AccountingLib.sol";

contract Relay {
        address operator;

        function Relay() {
                operator = msg.sender;
        }

        function relayCall(address contractAddress, bytes4 abiSignature, bytes data) public returns (bool) {
                if (msg.sender != operator) {
                        throw;
                }
                return contractAddress.call(abiSignature, data);
        }
}

library ScheduledCallLib {
    struct CallDatabase {
        Relay unauthorizedRelay;
        Relay authorizedRelay;

        bytes32 lastCallKey;
        bytes lastData;
        uint lastDataLength;
        bytes32 lastDataHash;

        ResourcePoolLib.Pool callerPool;
        GroveLib.Index callIndex;

        AccountingLib.Bank gasBank;

        mapping (bytes32 => Call) calls;
        mapping (bytes32 => bytes) data_registry;

        mapping (bytes32 => bool) accountAuthorizations;
    }

    struct Call {
            address contractAddress;
            address scheduledBy;
            uint calledAtBlock;
            uint targetBlock;
            uint8 gracePeriod;
            uint nonce;
            uint baseGasPrice;
            uint gasPrice;
            uint gasUsed;
            uint gasCost;
            uint payout;
            uint fee;
            address executedBy;
            bytes4 abiSignature;
            bool isCancelled;
            bool wasCalled;
            bool wasSuccessful;
            bytes32 dataHash;
    }

    // The author (Piper Merriam) address.
    address constant owner = 0xd3cda913deb6f67967b99d67acdfa1712c293601;

    /*
     *  Getter methods for `Call` information
     */
    function getCallContractAddress(CallDatabase storage self, bytes32 callKey) constant returns (address) {
            return self.calls[callKey].contractAddress;
    }

    function getCallScheduledBy(CallDatabase storage self, bytes32 callKey) constant returns (address) {
            return self.calls[callKey].scheduledBy;
    }

    function getCallCalledAtBlock(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].calledAtBlock;
    }

    function getCallGracePeriod(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].gracePeriod;
    }

    function getCallTargetBlock(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].targetBlock;
    }

    function getCallBaseGasPrice(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].baseGasPrice;
    }

    function getCallGasPrice(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].gasPrice;
    }

    function getCallGasUsed(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].gasUsed;
    }

    function getCallABISignature(CallDatabase storage self, bytes32 callKey) constant returns (bytes4) {
            return self.calls[callKey].abiSignature;
    }

    function checkIfCalled(CallDatabase storage self, bytes32 callKey) constant returns (bool) {
            return self.calls[callKey].wasCalled;
    }

    function checkIfSuccess(CallDatabase storage self, bytes32 callKey) constant returns (bool) {
            return self.calls[callKey].wasSuccessful;
    }

    function checkIfCancelled(CallDatabase storage self, bytes32 callKey) constant returns (bool) {
            return self.calls[callKey].isCancelled;
    }

    function getCallDataHash(CallDatabase storage self, bytes32 callKey) constant returns (bytes32) {
            return self.calls[callKey].dataHash;
    }

    function getCallPayout(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].payout;
    }

    function getCallFee(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].fee;
    }

    /*
     *  Scheduling Authorization API
     */

    function addAuthorization(CallDatabase storage self, address schedulerAddress, address contractAddress) public {
            self.accountAuthorizations[sha3(schedulerAddress, contractAddress)] = true;
    }

    function removeAuthorization(CallDatabase storage self, address schedulerAddress, address contractAddress) public {
            self.accountAuthorizations[sha3(schedulerAddress, contractAddress)] = false;
    }

    function checkAuthorization(CallDatabase storage self, address schedulerAddress, address contractAddress) constant returns (bool) {
            return self.accountAuthorizations[sha3(schedulerAddress, contractAddress)];
    }

    /*
     *  Data Registry API
     */
    function getCallData(CallDatabase storage self, bytes32 callKey) constant returns (bytes) {
            return self.data_registry[self.calls[callKey].dataHash];
    }

    /*
     *  API used by Alarm service
     */

    // TODO: these functions should be put in the ScheduledCallLib and
    // reworked since they used to be in the CallerPool contract.
    uint constant CALL_WINDOW_SIZE = 16;

    function getGenerationIdForCall(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            Call call = self.calls[callKey];
            return ResourcePoolLib.getGenerationForWindow(self.callerPool, call.targetBlock, call.targetBlock + call.gracePeriod);
    }

    function getDesignatedCaller(CallDatabase storage self, bytes32 callKey, uint blockNumber) constant returns (address) {
            /*
             *  Returns the caller from the current call pool who is
             *  designated as the executor of this call.
             */
            Call call = self.calls[callKey];
            if (blockNumber < call.targetBlock || blockNumber > call.targetBlock + call.gracePeriod) {
                    // blockNumber not within call window.
                    return 0x0;
            }

            // Check if we are in free-for-all window.
            uint numWindows = call.gracePeriod / CALL_WINDOW_SIZE;
            uint blockWindow = (blockNumber - call.targetBlock) / CALL_WINDOW_SIZE;

            if (blockWindow + 2 > numWindows) {
                    // We are within the free-for-all period.
                    return 0x0;
            }

            // Pool used is based on the starting block for the call.  This
            // allows us to know that the pool cannot change for at least
            // POOL_FREEZE_NUM_BLOCKS which is kept greater than the max
            // grace period.
            // TODO: this comment needs to be rewritten
            uint generationId = ResourcePoolLib.getGenerationForWindow(self.callerPool, call.targetBlock, call.targetBlock + call.gracePeriod);
            if (generationId == 0) {
                    // No pool currently in operation.
                    return 0x0;
            }
            var generation = self.callerPool.generations[generationId];

            uint offset = uint(callKey) % generation.members.length;
            return generation.members[(offset + blockWindow) % generation.members.length];
    }

    event _AwardedMissedBlockBonus(address indexed fromCaller, address indexed toCaller, uint indexed generationId, bytes32 callKey, uint blockNumber, uint bonusAmount);
    function AwardedMissedBlockBonus(address fromCaller, address toCaller, uint generationId, bytes32 callKey, uint blockNumber, uint bonusAmount) public {
        _AwardedMissedBlockBonus(fromCaller, toCaller, generationId, callKey, blockNumber, bonusAmount);
    }

    function getMinimumBond() constant returns (uint) {
            return tx.gasprice * block.gaslimit;
    }

    function doBondBonusTransfer(CallDatabase storage self, address fromCaller, address toCaller) internal returns (uint) {
            uint bonusAmount = getMinimumBond();
            uint bondBalance = self.callerPool.bonds[fromCaller];

            // If the bond balance is lower than the award
            // balance, then adjust the reward amount to
            // match the bond balance.
            if (bonusAmount > bondBalance) {
                    bonusAmount = bondBalance;
            }

            // Transfer the funds fromCaller => toCaller
            ResourcePoolLib.deductFromBond(self.callerPool, fromCaller, bonusAmount);
            ResourcePoolLib.addToBond(self.callerPool, toCaller, bonusAmount);

            return bonusAmount;
    }

    function awardMissedBlockBonus(CallDatabase storage self, address toCaller, bytes32 callKey) public {
            var call = self.calls[callKey];

            var generation = self.callerPool.generations[ResourcePoolLib.getGenerationForWindow(self.callerPool, call.targetBlock, call.targetBlock + call.gracePeriod)];
            uint i;
            uint bonusAmount;
            address fromCaller;

            uint numWindows = call.gracePeriod / CALL_WINDOW_SIZE;
            uint blockWindow = (block.number - call.targetBlock) / CALL_WINDOW_SIZE;

            // Check if we are within the free-for-all period.  If so, we
            // award from all pool members.
            if (blockWindow + 2 > numWindows) {
                    address firstCaller = getDesignatedCaller(self, callKey, call.targetBlock);
                    for (i = call.targetBlock; i <= call.targetBlock + call.gracePeriod; i += CALL_WINDOW_SIZE) {
                            fromCaller = getDesignatedCaller(self, callKey, i);
                            if (fromCaller == firstCaller && i != call.targetBlock) {
                                    // We have already gone through all of
                                    // the pool callers so we should break
                                    // out of the loop.
                                    break;
                            }
                            if (fromCaller == toCaller) {
                                    continue;
                            }
                            bonusAmount = doBondBonusTransfer(self, fromCaller, toCaller);

                            // Log the bonus was awarded.
                            AwardedMissedBlockBonus(fromCaller, toCaller, generation.id, callKey, block.number, bonusAmount);
                    }
                    return;
            }

            // Special case for single member and empty pools
            if (generation.members.length < 2) {
                    return;
            }

            // Otherwise the award comes from the previous caller.
            for (i = 0; i < generation.members.length; i++) {
                    // Find where the member is in the pool and
                    // award from the previous pool members bond.
                    if (generation.members[i] == toCaller) {
                            fromCaller = generation.members[(i + generation.members.length - 1) % generation.members.length];

                            bonusAmount = doBondBonusTransfer(self, fromCaller, toCaller);

                            // Log the bonus was awarded.
                            AwardedMissedBlockBonus(fromCaller, toCaller, generation.id, callKey, block.number, bonusAmount);

                            // Remove the caller from the next pool.
                            if (ResourcePoolLib.getNextGenerationId(self.callerPool) == 0) {
                                    // This is the first address to modify the
                                    // current pool so we need to setup the next
                                    // pool.
                                    ResourcePoolLib.createNextGeneration(self.callerPool);
                            }
                            ResourcePoolLib.removeFromGeneration(self.callerPool, ResourcePoolLib.getNextGenerationId(self.callerPool), fromCaller);
                            return;
                    }
            }
    }

    /*
     *  Data registration API
     */
    event _DataRegistered(bytes32 indexed dataHash);
    function DataRegistered(bytes32 dataHash) constant {
        _DataRegistered(dataHash);
    }

    function registerData(CallDatabase storage self, bytes data) public {
            self.lastData.length = data.length - 4;
            if (data.length > 4) {
                    for (uint i = 0; i < self.lastData.length; i++) {
                            self.lastData[i] = data[i + 4];
                    }
            }
            self.data_registry[sha3(self.lastData)] = self.lastData;
            self.lastDataHash = sha3(self.lastData);
            self.lastDataLength = self.lastData.length;
    }

    /*
     *  Call execution API
     */
    // This number represents the constant gas cost of the addition
    // operations that occur in `doCall` that cannot be tracked with
    // msg.gas.
    // TODO: recompute this value
    //uint constant EXTRA_CALL_GAS = 151098;
    //uint constant EXTRA_CALL_GAS = 160574;
    //uint constant EXTRA_CALL_GAS = 160143;
    //uint constant EXTRA_CALL_GAS = 160229;
    //uint constant EXTRA_CALL_GAS = 153037;
    uint constant EXTRA_CALL_GAS = 153145;

    // This number represents the overall overhead involved in executing a
    // scheduled call.
    // TODO: recompute this value
    //uint constant CALL_OVERHEAD = 144982;
    //uint constant CALL_OVERHEAD = 127077;
    uint constant CALL_OVERHEAD = 120104;

    event _CallExecuted(address indexed executedBy, bytes32 indexed callKey);
    function CallExecuted(address executedBy, bytes32 callKey) public {
        _CallExecuted(executedBy, callKey);
    }
    event _CallAborted(address indexed executedBy, bytes32 indexed callKey, bytes18 reason);
    function CallAborted(address executedBy, bytes32 callKey, bytes18 reason) public {
        _CallAborted(executedBy, callKey, reason);
    }

    function doCall(CallDatabase storage self, bytes32 callKey, address msgSender) public {
            uint gasBefore = msg.gas;

            Call storage call = self.calls[callKey];

            if (call.wasCalled) {
                    // The call has already been executed so don't do it again.
                    _CallAborted(msg.sender, callKey, "ALREADY CALLED");
                    return;
            }

            if (call.isCancelled) {
                    // The call was cancelled so don't execute it.
                    _CallAborted(msg.sender, callKey, "CANCELLED");
                    return;
            }

            if (call.contractAddress == 0x0) {
                    // This call key doesnt map to a registered call.
                    _CallAborted(msg.sender, callKey, "UNKNOWN");
                    return;
            }

            if (block.number < call.targetBlock) {
                    // Target block hasnt happened yet.
                    _CallAborted(msg.sender, callKey, "TOO EARLY");
                    return;
            }

            if (block.number > call.targetBlock + call.gracePeriod) {
                    // The blockchain has advanced passed the period where
                    // it was allowed to be called.
                    _CallAborted(msg.sender, callKey, "TOO LATE");
                    return;
            }

            uint heldBalance = getCallMaxCost(self, callKey);

            if (self.gasBank.accountBalances[call.scheduledBy] < heldBalance) {
                    // The scheduledBy's account balance is less than the
                    // current gasLimit and thus potentiall can't pay for
                    // the call.

                    // Mark it as called since it was.
                    call.wasCalled = true;

                    // Log it.
                    _CallAborted(msg.sender, callKey, "INSUFFICIENT_FUNDS");
                    return;
            }

            // Check if this caller is allowed to execute the call.
            if (self.callerPool.generations[ResourcePoolLib.getCurrentGenerationId(self.callerPool)].members.length > 0) {
                    address designatedCaller = getDesignatedCaller(self, callKey, block.number);
                    if (designatedCaller != 0x0 && designatedCaller != msgSender) {
                            // This call was reserved for someone from the
                            // bonded pool of callers and can only be
                            // called by them during this block window.
                            _CallAborted(msg.sender, callKey, "WRONG_CALLER");
                            return;
                    }

                    uint blockWindow = (block.number - call.targetBlock) / CALL_WINDOW_SIZE;
                    if (blockWindow > 0) {
                            // Someone missed their call so this caller
                            // gets to claim their bond for picking up
                            // their slack.
                            awardMissedBlockBonus(self, msgSender, callKey);
                    }
            }

            // Log metadata about the call.
            call.gasPrice = tx.gasprice;
            call.executedBy = msgSender;
            call.calledAtBlock = block.number;

            // Fetch the call data
            var data = self.data_registry[call.dataHash];

            // During the call, we need to put enough funds to pay for the
            // call on hold to ensure they are available to pay the caller.
            AccountingLib.withdraw(self.gasBank, call.scheduledBy, heldBalance);

            // Mark whether the function call was successful.
            if (checkAuthorization(self, call.scheduledBy, call.contractAddress)) {
                    call.wasSuccessful = self.authorizedRelay.relayCall.gas(msg.gas - CALL_OVERHEAD)(call.contractAddress, call.abiSignature, data);
            }
            else {
                    call.wasSuccessful = self.unauthorizedRelay.relayCall.gas(msg.gas - CALL_OVERHEAD)(call.contractAddress, call.abiSignature, data);
            }

            // Add the held funds back into the scheduler's account.
            AccountingLib.deposit(self.gasBank, call.scheduledBy, heldBalance);

            // Mark the call as having been executed.
            call.wasCalled = true;

            // Compute the scalar (0 - 200) for the fee.
            uint feeScalar = getCallFeeScalar(call.baseGasPrice, call.gasPrice);

            // Log how much gas this call used.  EXTRA_CALL_GAS is a fixed
            // amount that represents the gas usage of the commands that
            // happen after this line.
            call.gasUsed = (gasBefore - msg.gas + EXTRA_CALL_GAS);
            call.gasCost = call.gasUsed * call.gasPrice;

            // Now we need to pay the caller as well as keep fee.
            // callerPayout -> call cost + 1%
            // fee -> 1% of callerPayout
            call.payout = call.gasCost * feeScalar * 101 / 10000;
            call.fee = call.gasCost * feeScalar / 10000;

            AccountingLib.deductFunds(self.gasBank, call.scheduledBy, call.payout + call.fee);

            AccountingLib.addFunds(self.gasBank, msgSender, call.payout);
            AccountingLib.addFunds(self.gasBank, owner, call.fee);
    }

    function getCallMaxCost(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            /*
             *  tx.gasprice * block.gaslimit
             *
             */
            // call cost + 2%
            var call = self.calls[callKey];

            uint gasCost = tx.gasprice * block.gaslimit;
            uint feeScalar = getCallFeeScalar(call.baseGasPrice, tx.gasprice);

            return gasCost * feeScalar * 102 / 10000;
    }

    function getCallFeeScalar(uint baseGasPrice, uint gasPrice) constant returns (uint) {
            /*
             *  Return a number between 0 - 200 to scale the fee based on
             *  the gas price set for the calling transaction as compared
             *  to the gas price of the scheduling transaction.
             *
             *  - number approaches zero as the transaction gas price goes
             *  above the gas price recorded when the call was scheduled.
             *
             *  - the number approaches 200 as the transaction gas price
             *  drops under the price recorded when the call was scheduled.
             *
             *  This encourages lower gas costs as the lower the gas price
             *  for the executing transaction, the higher the payout to the
             *  caller.
             */
            if (gasPrice > baseGasPrice) {
                    return 100 * baseGasPrice / gasPrice;
            }
            else {
                    return 200 - 100 * baseGasPrice / (2 * baseGasPrice - gasPrice);
            }
    }

    /*
     *  Call Scheduling API
     */

    // The result of `sha()` so that we can validate that people aren't
    // looking up call data that failed to register.
    bytes32 constant emptyDataHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

    function computeCallKey(address scheduledBy, address contractAddress, bytes4 abiSignature, bytes32 dataHash, uint targetBlock, uint8 gracePeriod, uint nonce) constant returns (bytes32) {
            return sha3(scheduledBy, contractAddress, abiSignature, dataHash, targetBlock, gracePeriod, nonce);
    }

    // Ten minutes into the future.
    uint constant MAX_BLOCKS_IN_FUTURE = 40;

    event _CallScheduled(bytes32 indexed callKey);
    function CallScheduled(bytes32 callKey) public {
        _CallScheduled(callKey);
    }
    event _CallRejected(bytes32 indexed callKey, bytes15 reason);
    function CallRejected(bytes32 callKey, bytes15 reason) public {
        _CallRejected(callKey, reason);
    }

    function getCallWindowSize() public returns (uint) {
        return CALL_WINDOW_SIZE;
    }

    function getMinimumGracePeriod() public returns (uint) {
        return 4 * CALL_WINDOW_SIZE;
    }

    function scheduleCall(CallDatabase storage self, address schedulerAddress, address contractAddress, bytes4 abiSignature, bytes32 dataHash, uint targetBlock, uint8 gracePeriod, uint nonce) public returns (bytes15) {
            /*
             * Primary API for scheduling a call.  Prior to calling this
             * the data should already have been registered through the
             * `registerData` API.
             */
            bytes32 callKey = computeCallKey(schedulerAddress, contractAddress, abiSignature, dataHash, targetBlock, gracePeriod, nonce);

            if (dataHash != emptyDataHash && self.data_registry[dataHash].length == 0) {
                    // Don't allow registering calls if the data hash has
                    // not actually been registered.  The only exception is
                    // the *emptyDataHash*.
                    return "NO_DATA";
            }

            if (targetBlock < block.number + MAX_BLOCKS_IN_FUTURE) {
                    // Don't allow scheduling further than
                    // MAX_BLOCKS_IN_FUTURE
                    return "TOO_SOON";
            }
            Call storage call = self.calls[callKey];

            if (call.contractAddress != 0x0) {
                    return "DUPLICATE";
            }

            if (gracePeriod < getMinimumGracePeriod()) {
                    return "GRACE_TOO_SHORT";
            }

            self.lastCallKey = callKey;

            call.contractAddress = contractAddress;
            call.scheduledBy = schedulerAddress;
            call.nonce = nonce;
            call.abiSignature = abiSignature;
            call.dataHash = dataHash;
            call.targetBlock = targetBlock;
            call.gracePeriod = gracePeriod;
            call.baseGasPrice = tx.gasprice;

            // Put the call into the grove index.
            GroveLib.insert(self.callIndex, self.lastCallKey, int(call.targetBlock));

            return 0x0;
    }

    event _CallCancelled(bytes32 indexed callKey);
    function CallCancelled(bytes32 callKey) public {
        _CallCancelled(callKey);
    }

    // Two minutes
    uint constant MIN_CANCEL_WINDOW = 8;

    function cancelCall(CallDatabase storage self, bytes32 callKey, address msgSender) public returns (bool) {
            Call storage call = self.calls[callKey];
            if (call.scheduledBy != msgSender) {
                    // Nobody but the scheduler can cancel a call.
                    return false;
            }
            if (call.wasCalled) {
                    // No need to cancel a call that already was executed.
                    return false;
            }
            if (call.targetBlock - MIN_CANCEL_WINDOW <= block.number) {
                    // Call cannot be cancelled this close to execution.
                    return false;
            }
            call.isCancelled = true;
            return true;
    }
}

import "libraries/GroveLib.sol";
import "libraries/ResourcePoolLib.sol";
import "libraries/AccountingLib.sol";

contract Relay {
        address operator;

        function Relay() {
                operator = msg.sender;
        }

        function relayCall(address contractAddress, bytes4 abiSignature, bytes data) public returns (bool) {
                if (msg.sender != operator) {
                        throw;
                }
                return contractAddress.call(abiSignature, data);
        }
}

library ScheduledCallLib {
    struct CallDatabase {
        Relay unauthorizedRelay;
        Relay authorizedRelay;

        bytes32 lastCallKey;
        bytes lastData;
        uint lastDataLength;
        bytes32 lastDataHash;

        ResourcePoolLib.Pool callerPool;
        GroveLib.Index callIndex;

        AccountingLib.Bank gasBank;

        mapping (bytes32 => Call) calls;
        mapping (bytes32 => bytes) data_registry;

        mapping (bytes32 => bool) accountAuthorizations;
    }

    struct Call {
            address contractAddress;
            address scheduledBy;
            uint calledAtBlock;
            uint targetBlock;
            uint8 gracePeriod;
            uint nonce;
            uint baseGasPrice;
            uint gasPrice;
            uint gasUsed;
            uint gasCost;
            uint payout;
            uint fee;
            address executedBy;
            bytes4 abiSignature;
            bool isCancelled;
            bool wasCalled;
            bool wasSuccessful;
            bytes32 dataHash;
    }

    // The author (Piper Merriam) address.
    address constant owner = 0xd3cda913deb6f67967b99d67acdfa1712c293601;

    /*
     *  Getter methods for `Call` information
     */
    function getCallContractAddress(CallDatabase storage self, bytes32 callKey) constant returns (address) {
            return self.calls[callKey].contractAddress;
    }

    function getCallScheduledBy(CallDatabase storage self, bytes32 callKey) constant returns (address) {
            return self.calls[callKey].scheduledBy;
    }

    function getCallCalledAtBlock(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].calledAtBlock;
    }

    function getCallGracePeriod(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].gracePeriod;
    }

    function getCallTargetBlock(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].targetBlock;
    }

    function getCallBaseGasPrice(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].baseGasPrice;
    }

    function getCallGasPrice(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].gasPrice;
    }

    function getCallGasUsed(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].gasUsed;
    }

    function getCallABISignature(CallDatabase storage self, bytes32 callKey) constant returns (bytes4) {
            return self.calls[callKey].abiSignature;
    }

    function checkIfCalled(CallDatabase storage self, bytes32 callKey) constant returns (bool) {
            return self.calls[callKey].wasCalled;
    }

    function checkIfSuccess(CallDatabase storage self, bytes32 callKey) constant returns (bool) {
            return self.calls[callKey].wasSuccessful;
    }

    function checkIfCancelled(CallDatabase storage self, bytes32 callKey) constant returns (bool) {
            return self.calls[callKey].isCancelled;
    }

    function getCallDataHash(CallDatabase storage self, bytes32 callKey) constant returns (bytes32) {
            return self.calls[callKey].dataHash;
    }

    function getCallPayout(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].payout;
    }

    function getCallFee(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            return self.calls[callKey].fee;
    }

    /*
     *  Scheduling Authorization API
     */

    function addAuthorization(CallDatabase storage self, address schedulerAddress, address contractAddress) public {
            self.accountAuthorizations[sha3(schedulerAddress, contractAddress)] = true;
    }

    function removeAuthorization(CallDatabase storage self, address schedulerAddress, address contractAddress) public {
            self.accountAuthorizations[sha3(schedulerAddress, contractAddress)] = false;
    }

    function checkAuthorization(CallDatabase storage self, address schedulerAddress, address contractAddress) constant returns (bool) {
            return self.accountAuthorizations[sha3(schedulerAddress, contractAddress)];
    }

    /*
     *  Data Registry API
     */
    function getCallData(CallDatabase storage self, bytes32 callKey) constant returns (bytes) {
            return self.data_registry[self.calls[callKey].dataHash];
    }

    /*
     *  API used by Alarm service
     */

    // TODO: these functions should be put in the ScheduledCallLib and
    // reworked since they used to be in the CallerPool contract.
    uint constant CALL_WINDOW_SIZE = 16;

    function getGenerationIdForCall(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            Call call = self.calls[callKey];
            return ResourcePoolLib.getGenerationForWindow(self.callerPool, call.targetBlock, call.targetBlock + call.gracePeriod);
    }

    function getDesignatedCaller(CallDatabase storage self, bytes32 callKey, uint blockNumber) constant returns (address) {
            /*
             *  Returns the caller from the current call pool who is
             *  designated as the executor of this call.
             */
            Call call = self.calls[callKey];
            if (blockNumber < call.targetBlock || blockNumber > call.targetBlock + call.gracePeriod) {
                    // blockNumber not within call window.
                    return 0x0;
            }

            // Check if we are in free-for-all window.
            uint numWindows = call.gracePeriod / CALL_WINDOW_SIZE;
            uint blockWindow = (blockNumber - call.targetBlock) / CALL_WINDOW_SIZE;

            if (blockWindow + 2 > numWindows) {
                    // We are within the free-for-all period.
                    return 0x0;
            }

            // Pool used is based on the starting block for the call.  This
            // allows us to know that the pool cannot change for at least
            // POOL_FREEZE_NUM_BLOCKS which is kept greater than the max
            // grace period.
            // TODO: this comment needs to be rewritten
            uint generationId = ResourcePoolLib.getGenerationForWindow(self.callerPool, call.targetBlock, call.targetBlock + call.gracePeriod);
            if (generationId == 0) {
                    // No pool currently in operation.
                    return 0x0;
            }
            var generation = self.callerPool.generations[generationId];

            uint offset = uint(callKey) % generation.members.length;
            return generation.members[(offset + blockWindow) % generation.members.length];
    }

    event _AwardedMissedBlockBonus(address indexed fromCaller, address indexed toCaller, uint indexed generationId, bytes32 callKey, uint blockNumber, uint bonusAmount);
    function AwardedMissedBlockBonus(address fromCaller, address toCaller, uint generationId, bytes32 callKey, uint blockNumber, uint bonusAmount) public {
        _AwardedMissedBlockBonus(fromCaller, toCaller, generationId, callKey, blockNumber, bonusAmount);
    }

    function getMinimumBond() constant returns (uint) {
            return tx.gasprice * block.gaslimit;
    }

    function doBondBonusTransfer(CallDatabase storage self, address fromCaller, address toCaller) internal returns (uint) {
            uint bonusAmount = getMinimumBond();
            uint bondBalance = self.callerPool.bonds[fromCaller];

            // If the bond balance is lower than the award
            // balance, then adjust the reward amount to
            // match the bond balance.
            if (bonusAmount > bondBalance) {
                    bonusAmount = bondBalance;
            }

            // Transfer the funds fromCaller => toCaller
            ResourcePoolLib.deductFromBond(self.callerPool, fromCaller, bonusAmount);
            ResourcePoolLib.addToBond(self.callerPool, toCaller, bonusAmount);

            return bonusAmount;
    }

    function awardMissedBlockBonus(CallDatabase storage self, address toCaller, bytes32 callKey) public {
            var call = self.calls[callKey];

            var generation = self.callerPool.generations[ResourcePoolLib.getGenerationForWindow(self.callerPool, call.targetBlock, call.targetBlock + call.gracePeriod)];
            uint i;
            uint bonusAmount;
            address fromCaller;

            uint numWindows = call.gracePeriod / CALL_WINDOW_SIZE;
            uint blockWindow = (block.number - call.targetBlock) / CALL_WINDOW_SIZE;

            // Check if we are within the free-for-all period.  If so, we
            // award from all pool members.
            if (blockWindow + 2 > numWindows) {
                    address firstCaller = getDesignatedCaller(self, callKey, call.targetBlock);
                    for (i = call.targetBlock; i <= call.targetBlock + call.gracePeriod; i += 4) {
                            fromCaller = getDesignatedCaller(self, callKey, call.targetBlock);
                            if (fromCaller == firstCaller && i != call.targetBlock) {
                                    // We have already gone through all of
                                    // the pool callers so we should break
                                    // out of the loop.
                                    break;
                            }
                            if (fromCaller == toCaller) {
                                    continue;
                            }
                            bonusAmount = doBondBonusTransfer(self, fromCaller, toCaller);

                            // Log the bonus was awarded.
                            AwardedMissedBlockBonus(fromCaller, toCaller, generation.id, callKey, block.number, bonusAmount);
                    }
                    return;
            }

            // Special case for single member and empty pools
            if (generation.members.length < 2) {
                    return;
            }

            // Otherwise the award comes from the previous caller.
            for (i = 0; i < generation.members.length; i++) {
                    // Find where the member is in the pool and
                    // award from the previous pool members bond.
                    if (generation.members[i] == toCaller) {
                            fromCaller = generation.members[(i + generation.members.length - 1) % generation.members.length];

                            bonusAmount = doBondBonusTransfer(self, fromCaller, toCaller);

                            // Log the bonus was awarded.
                            AwardedMissedBlockBonus(fromCaller, toCaller, generation.id, callKey, block.number, bonusAmount);

                            // Remove the caller from the next pool.
                            if (ResourcePoolLib.getNextGenerationId(self.callerPool) == 0) {
                                    // This is the first address to modify the
                                    // current pool so we need to setup the next
                                    // pool.
                                    ResourcePoolLib.createNextGeneration(self.callerPool);
                            }
                            ResourcePoolLib.removeFromGeneration(self.callerPool, ResourcePoolLib.getNextGenerationId(self.callerPool), fromCaller);
                            return;
                    }
            }
    }

    /*
     *  Data registration API
     */
    event _DataRegistered(bytes32 indexed dataHash);
    function DataRegistered(bytes32 dataHash) constant {
        _DataRegistered(dataHash);
    }

    function registerData(CallDatabase storage self, bytes data) public {
            self.lastData.length = data.length - 4;
            if (data.length > 4) {
                    for (uint i = 0; i < self.lastData.length; i++) {
                            self.lastData[i] = data[i + 4];
                    }
            }
            self.data_registry[sha3(self.lastData)] = self.lastData;
            self.lastDataHash = sha3(self.lastData);
            self.lastDataLength = self.lastData.length;
    }

    /*
     *  Call execution API
     */
    // This number represents the constant gas cost of the addition
    // operations that occur in `doCall` that cannot be tracked with
    // msg.gas.
    // TODO: recompute this value
    //uint constant EXTRA_CALL_GAS = 151098;
    //uint constant EXTRA_CALL_GAS = 160574;
    //uint constant EXTRA_CALL_GAS = 160143;
    //uint constant EXTRA_CALL_GAS = 160229;
    //uint constant EXTRA_CALL_GAS = 153037;
    uint constant EXTRA_CALL_GAS = 153145;

    // This number represents the overall overhead involved in executing a
    // scheduled call.
    // TODO: recompute this value
    //uint constant CALL_OVERHEAD = 144982;
    //uint constant CALL_OVERHEAD = 127077;
    uint constant CALL_OVERHEAD = 120104;

    event _CallExecuted(address indexed executedBy, bytes32 indexed callKey);
    function CallExecuted(address executedBy, bytes32 callKey) public {
        _CallExecuted(executedBy, callKey);
    }
    event _CallAborted(address indexed executedBy, bytes32 indexed callKey, bytes18 reason);
    function CallAborted(address executedBy, bytes32 callKey, bytes18 reason) public {
        _CallAborted(executedBy, callKey, reason);
    }

    function doCall(CallDatabase storage self, bytes32 callKey, address msgSender) public {
            uint gasBefore = msg.gas;

            Call storage call = self.calls[callKey];

            if (call.wasCalled) {
                    // The call has already been executed so don't do it again.
                    _CallAborted(msg.sender, callKey, "ALREADY CALLED");
                    return;
            }

            if (call.isCancelled) {
                    // The call was cancelled so don't execute it.
                    _CallAborted(msg.sender, callKey, "CANCELLED");
                    return;
            }

            if (call.contractAddress == 0x0) {
                    // This call key doesnt map to a registered call.
                    _CallAborted(msg.sender, callKey, "UNKNOWN");
                    return;
            }

            if (block.number < call.targetBlock) {
                    // Target block hasnt happened yet.
                    _CallAborted(msg.sender, callKey, "TOO EARLY");
                    return;
            }

            if (block.number > call.targetBlock + call.gracePeriod) {
                    // The blockchain has advanced passed the period where
                    // it was allowed to be called.
                    _CallAborted(msg.sender, callKey, "TOO LATE");
                    return;
            }

            uint heldBalance = getCallMaxCost(self, callKey);

            if (self.gasBank.accountBalances[call.scheduledBy] < heldBalance) {
                    // The scheduledBy's account balance is less than the
                    // current gasLimit and thus potentiall can't pay for
                    // the call.

                    // Mark it as called since it was.
                    call.wasCalled = true;

                    // Log it.
                    _CallAborted(msg.sender, callKey, "INSUFFICIENT_FUNDS");
                    return;
            }

            // Check if this caller is allowed to execute the call.
            if (self.callerPool.generations[ResourcePoolLib.getCurrentGenerationId(self.callerPool)].members.length > 0) {
                    address designatedCaller = getDesignatedCaller(self, callKey, block.number);
                    if (designatedCaller != 0x0 && designatedCaller != msgSender) {
                            // This call was reserved for someone from the
                            // bonded pool of callers and can only be
                            // called by them during this block window.
                            _CallAborted(msg.sender, callKey, "WRONG_CALLER");
                            return;
                    }

                    uint blockWindow = (block.number - call.targetBlock) / CALL_WINDOW_SIZE;
                    if (blockWindow > 0) {
                            // Someone missed their call so this caller
                            // gets to claim their bond for picking up
                            // their slack.
                            awardMissedBlockBonus(self, msgSender, callKey);
                    }
            }

            // Log metadata about the call.
            call.gasPrice = tx.gasprice;
            call.executedBy = msgSender;
            call.calledAtBlock = block.number;

            // Fetch the call data
            var data = self.data_registry[call.dataHash];

            // During the call, we need to put enough funds to pay for the
            // call on hold to ensure they are available to pay the caller.
            AccountingLib.withdraw(self.gasBank, call.scheduledBy, heldBalance);

            // Mark whether the function call was successful.
            if (checkAuthorization(self, call.scheduledBy, call.contractAddress)) {
                    call.wasSuccessful = self.authorizedRelay.relayCall.gas(msg.gas - CALL_OVERHEAD)(call.contractAddress, call.abiSignature, data);
            }
            else {
                    call.wasSuccessful = self.unauthorizedRelay.relayCall.gas(msg.gas - CALL_OVERHEAD)(call.contractAddress, call.abiSignature, data);
            }

            // Add the held funds back into the scheduler's account.
            AccountingLib.deposit(self.gasBank, call.scheduledBy, heldBalance);

            // Mark the call as having been executed.
            call.wasCalled = true;

            // Compute the scalar (0 - 200) for the fee.
            uint feeScalar = getCallFeeScalar(call.baseGasPrice, call.gasPrice);

            // Log how much gas this call used.  EXTRA_CALL_GAS is a fixed
            // amount that represents the gas usage of the commands that
            // happen after this line.
            call.gasUsed = (gasBefore - msg.gas + EXTRA_CALL_GAS);
            call.gasCost = call.gasUsed * call.gasPrice;

            // Now we need to pay the caller as well as keep fee.
            // callerPayout -> call cost + 1%
            // fee -> 1% of callerPayout
            call.payout = call.gasCost * feeScalar * 101 / 10000;
            call.fee = call.gasCost * feeScalar / 10000;

            AccountingLib.deductFunds(self.gasBank, call.scheduledBy, call.payout + call.fee);

            AccountingLib.addFunds(self.gasBank, msgSender, call.payout);
            AccountingLib.addFunds(self.gasBank, owner, call.fee);
    }

    function getCallMaxCost(CallDatabase storage self, bytes32 callKey) constant returns (uint) {
            /*
             *  tx.gasprice * block.gaslimit
             *
             */
            // call cost + 2%
            var call = self.calls[callKey];

            uint gasCost = tx.gasprice * block.gaslimit;
            uint feeScalar = getCallFeeScalar(call.baseGasPrice, tx.gasprice);

            return gasCost * feeScalar * 102 / 10000;
    }

    function getCallFeeScalar(uint baseGasPrice, uint gasPrice) constant returns (uint) {
            /*
             *  Return a number between 0 - 200 to scale the fee based on
             *  the gas price set for the calling transaction as compared
             *  to the gas price of the scheduling transaction.
             *
             *  - number approaches zero as the transaction gas price goes
             *  above the gas price recorded when the call was scheduled.
             *
             *  - the number approaches 200 as the transaction gas price
             *  drops under the price recorded when the call was scheduled.
             *
             *  This encourages lower gas costs as the lower the gas price
             *  for the executing transaction, the higher the payout to the
             *  caller.
             */
            if (gasPrice > baseGasPrice) {
                    return 100 * baseGasPrice / gasPrice;
            }
            else {
                    return 200 - 100 * baseGasPrice / (2 * baseGasPrice - gasPrice);
            }
    }

    /*
     *  Call Scheduling API
     */

    // The result of `sha()` so that we can validate that people aren't
    // looking up call data that failed to register.
    bytes32 constant emptyDataHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

    function computeCallKey(address scheduledBy, address contractAddress, bytes4 abiSignature, bytes32 dataHash, uint targetBlock, uint8 gracePeriod, uint nonce) constant returns (bytes32) {
            return sha3(scheduledBy, contractAddress, abiSignature, dataHash, targetBlock, gracePeriod, nonce);
    }

    // Ten minutes into the future.
    uint constant MAX_BLOCKS_IN_FUTURE = 40;

    event _CallScheduled(bytes32 indexed callKey);
    function CallScheduled(bytes32 callKey) public {
        _CallScheduled(callKey);
    }
    event _CallRejected(bytes32 indexed callKey, bytes15 reason);
    function CallRejected(bytes32 callKey, bytes15 reason) public {
        _CallRejected(callKey, reason);
    }

    function getCallWindowSize() public returns (uint) {
        return CALL_WINDOW_SIZE;
    }

    function getMinimumGracePeriod() public returns (uint) {
        return 4 * CALL_WINDOW_SIZE;
    }

    function scheduleCall(CallDatabase storage self, address schedulerAddress, address contractAddress, bytes4 abiSignature, bytes32 dataHash, uint targetBlock, uint8 gracePeriod, uint nonce) public returns (bytes15) {
            /*
             * Primary API for scheduling a call.  Prior to calling this
             * the data should already have been registered through the
             * `registerData` API.
             */
            bytes32 callKey = computeCallKey(schedulerAddress, contractAddress, abiSignature, dataHash, targetBlock, gracePeriod, nonce);

            if (dataHash != emptyDataHash && self.data_registry[dataHash].length == 0) {
                    // Don't allow registering calls if the data hash has
                    // not actually been registered.  The only exception is
                    // the *emptyDataHash*.
                    return "NO_DATA";
            }

            if (targetBlock < block.number + MAX_BLOCKS_IN_FUTURE) {
                    // Don't allow scheduling further than
                    // MAX_BLOCKS_IN_FUTURE
                    return "TOO_SOON";
            }
            Call storage call = self.calls[callKey];

            if (call.contractAddress != 0x0) {
                    return "DUPLICATE";
            }

            if (gracePeriod < getMinimumGracePeriod()) {
                    return "GRACE_TOO_SHORT";
            }

            self.lastCallKey = callKey;

            call.contractAddress = contractAddress;
            call.scheduledBy = schedulerAddress;
            call.nonce = nonce;
            call.abiSignature = abiSignature;
            call.dataHash = dataHash;
            call.targetBlock = targetBlock;
            call.gracePeriod = gracePeriod;
            call.baseGasPrice = tx.gasprice;

            // Put the call into the grove index.
            GroveLib.insert(self.callIndex, self.lastCallKey, int(call.targetBlock));

            return 0x0;
    }

    event _CallCancelled(bytes32 indexed callKey);
    function CallCancelled(bytes32 callKey) public {
        _CallCancelled(callKey);
    }

    // Two minutes
    uint constant MIN_CANCEL_WINDOW = 8;

    function cancelCall(CallDatabase storage self, bytes32 callKey, address msgSender) public returns (bool) {
            Call storage call = self.calls[callKey];
            if (call.scheduledBy != msgSender) {
                    // Nobody but the scheduler can cancel a call.
                    return false;
            }
            if (call.wasCalled) {
                    // No need to cancel a call that already was executed.
                    return false;
            }
            if (call.targetBlock - MIN_CANCEL_WINDOW <= block.number) {
                    // Call cannot be cancelled this close to execution.
                    return false;
            }
            call.isCancelled = true;
            return true;
    }
}


The total coins the contract has is used to compute the burn, cant allow any claims before that

pragma solidity ^0.4.11;

/**
* Copyright 2017 Veterapreneur
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/

/**
 * Math operations with safety checks
 */
library SafeMath {
    function mul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function div(uint a, uint b) internal returns (uint) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }

    function sub(uint a, uint b) internal returns (uint) {
        assert(b <= a);
        return a - b;
    }

    function add(uint a, uint b) internal returns (uint) {
        uint c = a + b;
        assert(c >= a);
        return c;
    }
}

contract owned {

    address public owner;

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

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

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

contract token {
    function balanceOf(address owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function burn(uint256 value) returns(bool success);
}

contract VeteranCoinSale is owned {

    using SafeMath for uint256;

    uint  public tokenSold;
    uint  public startDate;
    uint  public deadline;
    uint  public weekTwo;
    uint  public weekThree;
    uint  public weekFour;
    // how many token units a buyer gets per wei
    uint  public rate;
    bool  crowdsaleClosed = false;
    bool burned = false;
    token tokenReward;

    event GoalReached(address _beneficiary);
    event CrowdSaleClosed(address _beneficiary);
    event BurnedExcessTokens(address _beneficiary, uint _amountBurned);
    event Refunded(address _beneficiary, uint _depositedValue);
    event FundTransfer(address _backer, uint _amount, bool _isContribution);
    event TokenPurchase(address _backer, uint _amount, uint _tokenAmt);
    event TokenClaim(address _backer, uint _tokenAmt);
    event BonusRateChange(uint _rate);

    /* data structure to hold information about campaign contributors */

    // how many token units a buyer gets per wei
    mapping(bytes32 => uint)  bonusSchedule;
    mapping(address => uint256)  balances;
    mapping(address => uint256)  beneficiaryTokens;

    /*  at initialization, setup the owner */
    function VeteranCoinSale(address _fundManager, uint _week1BonusRate, uint _week2BonusRate,
    uint _week3BonusRate, uint _week4BonusRate, token addressOfTokenUsedAsReward ) {

        if(_fundManager != 0){
            owner = _fundManager;
        }

        require(_week1BonusRate > 0);
        require(_week2BonusRate > 0);
        require(_week3BonusRate > 0);
        require(_week4BonusRate > 0);

        bonusSchedule["week1"] =  _week1BonusRate;
        bonusSchedule["week2"] =  _week2BonusRate;
        bonusSchedule["week3"] =  _week3BonusRate;
        bonusSchedule["week4"] =  _week4BonusRate;

        require( bonusSchedule["week1"] > bonusSchedule["week2"]);
        require( bonusSchedule["week2"] > bonusSchedule["week3"]);
        require( bonusSchedule["week3"] > bonusSchedule["week4"]);

        tokenReward = token(addressOfTokenUsedAsReward);

        tokenSold = 0;
        startDate = now;
        // todo move the times into ctr
        deadline = startDate + 4 minutes;
        weekTwo = startDate + 1 minutes;
        weekThree = startDate + 2 minutes;
        weekFour = startDate + 3 minutes;

        //sanity checks
        require(startDate < deadline);
        require(weekTwo < weekThree);
        require(weekThree < weekFour);

        // set rate according to bonus schedule for week 1
        rate = bonusSchedule["week1"];

    }

    modifier afterDeadline() { if (now >= deadline) _; }
    modifier releaseTheHounds(){ if (now >= startDate) _;}
    modifier callOffTheDogs(){ if (!crowdsaleClosed) _;}
    modifier allBurned(){if (burned) _;}
    modifier notBurned() {if (!burned) _;}

    /**
    * @dev tokens can be claimed() after the sale and only after the burn
    */
    function claimToken() public afterDeadline allBurned {
        uint tokens = beneficiaryTokens[msg.sender];
        if(tokens > 0){
            beneficiaryTokens[msg.sender] = 0;
            tokenReward.transfer(msg.sender, tokens);
            TokenClaim(msg.sender, tokens);
        }
    }

    //todo looks like modifiers don't work on payable, whoa!!
    /**
    *  @dev buy tokens here, claim tokens after sale ends!
    */
    function buyTokens() releaseTheHounds callOffTheDogs payable  {
        require (msg.sender != 0x0);
        uint weiAmount = msg.value;

        balances[msg.sender]  = balances[msg.sender].add(weiAmount);
        uint256 tokens = weiAmount.mul(rate);

        FundTransfer(msg.sender, weiAmount, true);
        TokenPurchase(msg.sender, weiAmount, tokens);
        beneficiaryTokens[msg.sender] = beneficiaryTokens[msg.sender].add(tokens);
        tokenSold = tokenSold.add(tokens);

        checkFundingGoalReached();
        adjustBonusPrice();
    }

    /**
     *
     *    @dev balances of wei sent to this contract
     *    @param _beneficiary number of tokens prior to claim
     *
     */
    function tokenBalanceOf(address _beneficiary) public constant returns (uint256 balance){
        return beneficiaryTokens[_beneficiary];
    }

    /**
     *
     *   @dev balances of wei sent this contract currently holds
     *    @param _beneficiary how much wei this address sent to contract
     */
    function balanceOf(address _beneficiary) public constant returns (uint256 balance){
        return balances[_beneficiary];
    }

    /**
    * @dev tokens must be claimed() first, then approved() in coin contract to owner address by "token holder" prior to refund
    * @param _beneficiary The investor getting the refund
    * @param _tokens number of be transferred.
    */
    function refund(address _beneficiary, uint _tokens) public onlyOwner afterDeadline {
        require(beneficiaryTokens[_beneficiary] == 0);
        require(tokenReward.transferFrom(_beneficiary, owner, _tokens));
        uint256 depositedValue = balances[_beneficiary];
        balances[_beneficiary] = 0;
        tokenSold = tokenSold.sub(_tokens);
        _beneficiary.transfer(depositedValue);
        Refunded(_beneficiary, depositedValue);
    }
    /*
    * @dev set a new rate
    * @param how many token units a buyer gets per wei
    */
    function setRate(uint256 _newRate) public onlyOwner{
        require(_newRate >0);
        rate = _newRate;
    }

    /**
    *   @dev make two checks before writing new rate
    */
    function adjustBonusPrice() internal {
        if (now >= weekTwo && now < weekThree){
            if(rate != bonusSchedule["week2"]){
                rate = bonusSchedule["week2"];
                BonusRateChange(rate);
            }
        }
        if (now >= weekThree && now < weekFour){
            if(rate != bonusSchedule["week3"]){
                rate = bonusSchedule["week3"];
                BonusRateChange(rate);
            }
        }
        if(now >= weekFour){
            if(rate != bonusSchedule["week4"]){
                rate = bonusSchedule["week4"];
                BonusRateChange(rate);
            }
        }
    }

    /**
     * @dev when token's sold = token balance, it's over
     *
     */
    function checkFundingGoalReached() internal {
        if(tokenSold == tokenReward.balanceOf(this)){
            crowdsaleClosed = true;
            GoalReached(owner);
        }
    }

    /**
    * @dev auto burn the tokens
    *
    */
    function autoBurn() public onlyOwner notBurned {
        crowdsaleClosed = true;
        uint256 burnPile = tokenReward.balanceOf(this).sub(tokenSold);
        if(burnPile > 0){
            tokenReward.burn(burnPile);
            BurnedExcessTokens(owner, burnPile);
        }
        burned = true;
    }

    function closeSale() public onlyOwner{
        crowdsaleClosed = true;
        CrowdSaleClosed(owner);
    }

    /**
    * @dev owner can safely withdraw contract value
    */
    function safeWithdrawal() public onlyOwner{
        uint256 balance = this.balance;
        if(owner.send(balance)){
            FundTransfer(owner,balance,false);
        }
    }

    // @return true if crowdsale event has ended
    function hasEnded() public constant returns (bool) {
        return crowdsaleClosed;
    }

}

pragma solidity ^0.4.11;

/**
* Copyright 2017 Veterapreneur
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/

/**
 * Math operations with safety checks
 */
library SafeMath {
    function mul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }

    function div(uint a, uint b) internal returns (uint) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }

    function sub(uint a, uint b) internal returns (uint) {
        assert(b <= a);
        return a - b;
    }

    function add(uint a, uint b) internal returns (uint) {
        uint c = a + b;
        assert(c >= a);
        return c;
    }
}

contract owned {

    address public owner;

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

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

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

contract token {
    function balanceOf(address owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function burn(uint256 value) returns(bool success);
}

contract VeteranCoinSale is owned {

    using SafeMath for uint256;

    uint  public tokenSold;
    uint  public startDate;
    uint  public deadline;
    uint  public weekTwo;
    uint  public weekThree;
    uint  public weekFour;
    // how many token units a buyer gets per wei
    uint  public rate;
    bool  crowdsaleClosed = false;
    bool burned = false;
    token tokenReward;

    event GoalReached(address _beneficiary);
    event CrowdSaleClosed(address _beneficiary);
    event BurnedExcessTokens(address _beneficiary, uint _amountBurned);
    event Refunded(address _beneficiary, uint _depositedValue);
    event FundTransfer(address _backer, uint _amount, bool _isContribution);
    event TokenPurchase(address _backer, uint _amount, uint _tokenAmt);
    event TokenClaim(address _backer, uint _tokenAmt);
    event BonusRateChange(uint _rate);

    /* data structure to hold information about campaign contributors */

    // how many token units a buyer gets per wei
    mapping(bytes32 => uint)  bonusSchedule;
    mapping(address => uint256)  balances;
    mapping(address => uint256)  beneficiaryTokens;

    /*  at initialization, setup the owner */
    function VeteranCoinSale(address _fundManager, uint _week1BonusRate, uint _week2BonusRate,
    uint _week3BonusRate, uint _week4BonusRate, token addressOfTokenUsedAsReward ) {

        if(_fundManager != 0){
            owner = _fundManager;
        }

        require(_week1BonusRate > 0);
        require(_week2BonusRate > 0);
        require(_week3BonusRate > 0);
        require(_week4BonusRate > 0);

        bonusSchedule["week1"] =  _week1BonusRate;
        bonusSchedule["week2"] =  _week2BonusRate;
        bonusSchedule["week3"] =  _week3BonusRate;
        bonusSchedule["week4"] =  _week4BonusRate;

        require( bonusSchedule["week1"] > bonusSchedule["week2"]);
        require( bonusSchedule["week2"] > bonusSchedule["week3"]);
        require( bonusSchedule["week3"] > bonusSchedule["week4"]);

        tokenReward = token(addressOfTokenUsedAsReward);

        tokenSold = 0;
        startDate = now;
        // todo move the times into ctr
        deadline = startDate + 4 minutes;
        weekTwo = startDate + 1 minutes;
        weekThree = startDate + 2 minutes;
        weekFour = startDate + 3 minutes;

        //sanity checks
        require(startDate < deadline);
        require(weekTwo < weekThree);
        require(weekThree < weekFour);

        // set rate according to bonus schedule for week 1
        rate = bonusSchedule["week1"];

    }

    modifier afterDeadline() { if (now >= deadline) _; }
    modifier releaseTheHounds(){ if (now >= startDate) _;}
    modifier callOffTheDogs(){ if (!crowdsaleClosed) _;}
    modifier allBurned(){if (!burned) _;}

    /**
    * @dev tokens must be claimed() after the sale
    */
    function claimToken() public afterDeadline {
        uint tokens = beneficiaryTokens[msg.sender];
        if(tokens > 0){
            beneficiaryTokens[msg.sender] = 0;
            tokenReward.transfer(msg.sender, tokens);
            TokenClaim(msg.sender, tokens);
        }
    }

    //todo looks like modifiers don't work on payable, whoa!!
    /**
    *  @dev buy tokens here, claim tokens after sale ends!
    */
    function buyTokens() releaseTheHounds callOffTheDogs payable  {
        require (msg.sender != 0x0);
        uint weiAmount = msg.value;

        balances[msg.sender]  = balances[msg.sender].add(weiAmount);
        uint256 tokens = weiAmount.mul(rate);

        FundTransfer(msg.sender, weiAmount, true);
        TokenPurchase(msg.sender, weiAmount, tokens);
        beneficiaryTokens[msg.sender] = beneficiaryTokens[msg.sender].add(tokens);
        tokenSold = tokenSold.add(tokens);

        checkFundingGoalReached();
        adjustBonusPrice();
    }

    /**
     *
     *    @dev balances of wei sent to this contract
     *    @param _beneficiary number of tokens prior to claim
     *
     */
    function tokenBalanceOf(address _beneficiary) public constant returns (uint256 balance){
        return beneficiaryTokens[_beneficiary];
    }

    /**
     *
     *   @dev balances of wei sent this contract currently holds
     *    @param _beneficiary how much wei this address sent to contract
     */
    function balanceOf(address _beneficiary) public constant returns (uint256 balance){
        return balances[_beneficiary];
    }

    /**
    * @dev tokens must be claimed() first, then approved() in coin contract to owner address by "token holder" prior to refund
    * @param _beneficiary The investor getting the refund
    * @param _tokens number of be transferred.
    */
    function refund(address _beneficiary, uint _tokens) public onlyOwner afterDeadline {
        require(beneficiaryTokens[_beneficiary] == 0);
        require(tokenReward.transferFrom(_beneficiary, owner, _tokens));
        uint256 depositedValue = balances[_beneficiary];
        balances[_beneficiary] = 0;
        tokenSold = tokenSold.sub(_tokens);
        _beneficiary.transfer(depositedValue);
        Refunded(_beneficiary, depositedValue);
    }
    /*
    * @dev set a new rate
    * @param how many token units a buyer gets per wei
    */
    function setRate(uint256 _newRate) public onlyOwner{
        require(_newRate >0);
        rate = _newRate;
    }

    /**
    *   @dev make two checks before writing new rate
    */
    function adjustBonusPrice() internal {
        if (now >= weekTwo && now < weekThree){
            if(rate != bonusSchedule["week2"]){
                rate = bonusSchedule["week2"];
                BonusRateChange(rate);
            }
        }
        if (now >= weekThree && now < weekFour){
            if(rate != bonusSchedule["week3"]){
                rate = bonusSchedule["week3"];
                BonusRateChange(rate);
            }
        }
        if(now >= weekFour){
            if(rate != bonusSchedule["week4"]){
                rate = bonusSchedule["week4"];
                BonusRateChange(rate);
            }
        }
    }

    /**
     * @dev when token's sold = token balance, it's over
     *
     */
    function checkFundingGoalReached() internal {
        if(tokenSold == tokenReward.balanceOf(this)){
            crowdsaleClosed = true;
            GoalReached(owner);
        }
    }

    /**
    * @dev auto burn the tokens
    * throws exception if balance < tokensold
    */
    function autoBurn() public onlyOwner allBurned {
        crowdsaleClosed = true;
        uint256 burnPile = tokenReward.balanceOf(this).sub(tokenSold);
        if(burnPile > 0){
            tokenReward.burn(burnPile);
            BurnedExcessTokens(owner, burnPile);
        }
        burned = true;
    }

    function closeSale() public onlyOwner{
        crowdsaleClosed = true;
        CrowdSaleClosed(owner);
    }

    /**
    * @dev owner can safely withdraw contract value
    */
    function safeWithdrawal() public onlyOwner{
        uint256 balance = this.balance;
        if(owner.send(balance)){
            FundTransfer(owner,balance,false);
        }
    }

    // @return true if crowdsale event has ended
    function hasEnded() public constant returns (bool) {
        return crowdsaleClosed;
    }

}


Updated Transfer event

Updated Transfer event

import "ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
	event Transfer(address indexed _from, address indexed _to, uint256 _value);

	mapping (address => uint) balances;

	function MetaCoin() {
		balances[tx.origin] = 10000;
	}

	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		Transfer(msg.sender, receiver, amount);
		return true;
	}
	function getBalanceInEth(address addr) returns(uint){
		return ConvertLib.convert(getBalance(addr),2);
	}
	function getBalance(address addr) returns(uint) {
		return balances[addr];
	}
}

import "ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
	mapping (address => uint) balances;

	function MetaCoin() {
		balances[tx.origin] = 10000;
	}

	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		return true;
	}
	function getBalanceInEth(address addr) returns(uint){
		return ConvertLib.convert(getBalance(addr),2);
	}
	function getBalance(address addr) returns(uint) {
		return balances[addr];
	}
	event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}