Overload ListLib.createNew() with no args

pragma solidity ^0.4.15;

import "../vendor/grove/GroveLib.sol";

import "./IntervalLib.sol";

library ListLib {
  uint8 constant SEARCH_DONE = 0x00;
  uint8 constant SEARCH_EARLIER = 0x01;
  uint8 constant SEARCH_LATER = 0x10;

  using GroveLib for GroveLib.Index;
  using IntervalLib for IntervalLib.Interval;

  struct List {
    uint length;
    uint center;

    // maps item ID to items
    mapping (uint => IntervalLib.Interval) items;

    GroveLib.Index beginIndex;
    GroveLib.Index endIndex;
    bytes32 lowestBegin;
    bytes32 highestEnd;
  }

  function createNew()
    internal
    returns (List)
  {
    return createNew(block.number);
  }

  function createNew(uint id)
    internal
    returns (List)
  {
    return List({
      length: 0,
      center: 0xDEADBEEF,
      lowestBegin: 0x0,
      highestEnd: 0x0,
      beginIndex: GroveLib.Index(sha3(this, bytes32(id * 2))),
      endIndex: GroveLib.Index(sha3(this, bytes32(id * 2 + 1)))
    });
  }

  function add(List storage list, uint begin, uint end, uint intervalID) internal {
    var _intervalID = bytes32(intervalID);
    var _begin = _getBeginIndexKey(begin);
    var _end = _getEndIndexKey(end);

    list.beginIndex.insert(_intervalID, _begin);
    list.endIndex.insert(_intervalID, _end);
    list.length++;

    if (list.length == 1) {
      list.lowestBegin = list.beginIndex.root;
      list.highestEnd = list.endIndex.root;
      list.center = begin + (end - begin) / 2;

      return;
    }

    var newLowest = list.beginIndex.getPreviousNode(list.lowestBegin);
    if (newLowest != 0x0) {
      list.lowestBegin = newLowest;
    }

    var newHighest = list.endIndex.getNextNode(list.highestEnd);
    if (newHighest != 0x0) {
      list.highestEnd = newHighest;
    }
  }

  /*
   * @dev Searches interval list for:
   *   - matching intervals
   *   - information on how search should proceed
   * @param node The node to search
   * @param point The point to search for
   */
  function matching(List storage list, uint point)
    constant
    internal
    returns (uint[] memory intervalIDs, uint8 searchNext)
  {
    uint[] memory _intervalIDs = new uint[](list.length);
    uint num = 0;

    bytes32 cur;

    if (point == list.center) {
      /*
       * case: point exactly matches the list's center
       *
       * collect (all) matching intervals (every interval in list, by def)
       */
      cur = list.lowestBegin;
      while (cur != 0x0) {
	_intervalIDs[num] = uint(list.beginIndex.getNodeId(cur));
	num++;
	cur = _next(list, cur);
      }

      /*
       * search is done:
       * no other nodes in tree have intervals containing point
       */
      searchNext = SEARCH_DONE;
    } else if (point < list.center) {
      /*
       * case: point is earlier than center.
       *
       *
       * collect matching intervals.
       *
       * shortcut:
       *
       *   starting with lowest beginning interval, search sorted begin list
       *   until begin is later than point
       *
       *	       point
       *                 :
       *                 :   center
       *                 :     |
       *        (0) *----:-----|----------o
       *        (1)    *-:-----|---o
       *        (-)      x *---|------o
       *        (-)         *--|--o
       *        (-)          *-|----o
       *
       *
       *    this works because intervals contained in an interval list are
       *    guaranteed tocontain `center`
       */
      cur = list.lowestBegin;
      while (cur != 0x0) {
	uint begin = _begin(list, cur);
	if (begin > point) {
	  break;
	}

	_intervalIDs[num] = uint(list.beginIndex.getNodeId(cur));
	num++;

	cur = _next(list, cur);
      }

      /*
       * search should proceed to earlier
       */
      searchNext = SEARCH_EARLIER;
    } else if (point > list.center) {
      /*
       * case: point is later than center.
       *
       *
       * collect matching intervals.
       *
       * shortcut:
       *
       *   starting with highest ending interval, search sorted end list
       *   until end is earlier than or equal to point
       *
       *			    point
       *			    :
       *                     center :
       *                       |    :
       *            *----------|----:-----o (0)
       *                   *---|----:-o     (1)
       *                     *-|----o	    (not matching, done.)
       *               *-------|---o	    (-)
       *                    *--|--o	    (-)
       *
       *
       *    this works because intervals contained in an interval list are
       *    guaranteed to contain `center`
       */
      cur = list.highestEnd;
      while (cur != 0x0) {
	uint end = _end(list, cur);
	if (end <= point) {
	  break;
	}

	_intervalIDs[num] = uint(list.endIndex.getNodeId(cur));
	num++;

	cur = _previous(list, cur);
      }

      /*
       * search proceeds to later intervals
       */
      searchNext = SEARCH_LATER;
    }

    /*
     * return correctly-sized array of intervalIDs
     */
    if (num == _intervalIDs.length) {
      intervalIDs = _intervalIDs;
    } else {
      intervalIDs = new uint[](num);
      for (uint i = 0; i < num; i++) {
	intervalIDs[i] = _intervalIDs[i];
      }
    }
  }

  /*
   * Grove linked list traversal
   */
  function _begin(List storage list, bytes32 indexNode) constant internal returns (uint) {
    return _getBegin(list.beginIndex.getNodeValue(indexNode));
  }

  function _end(List storage list, bytes32 indexNode) constant internal returns (uint) {
    return _getEnd(list.endIndex.getNodeValue(indexNode));
  }

  function _next(List storage list, bytes32 cur) constant internal returns (bytes32) {
    return list.beginIndex.getNextNode(cur);
  }

  function _previous(List storage list, bytes32 cur) constant internal returns (bytes32) {
    return list.endIndex.getPreviousNode(cur);
  }

  /*
   * uint / int conversions for Grove nodeIDs
   */
  function _getBeginIndexKey(uint begin) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(begin - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getEndIndexKey(uint end) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(end - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getBegin(int beginIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(beginIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }

  function _getEnd(int endIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(endIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }
}

pragma solidity ^0.4.15;

import "../vendor/grove/GroveLib.sol";

import "./IntervalLib.sol";

library ListLib {
  uint8 constant SEARCH_DONE = 0x00;
  uint8 constant SEARCH_EARLIER = 0x01;
  uint8 constant SEARCH_LATER = 0x10;

  using GroveLib for GroveLib.Index;
  using IntervalLib for IntervalLib.Interval;

  struct List {
    uint length;
    uint center;

    // maps item ID to items
    mapping (uint => IntervalLib.Interval) items;

    GroveLib.Index beginIndex;
    GroveLib.Index endIndex;
    bytes32 lowestBegin;
    bytes32 highestEnd;
  }

  function createNew(uint id)
    internal
    returns (List)
  {
    return List({
      length: 0,
      center: 0xDEADBEEF,
      lowestBegin: 0x0,
      highestEnd: 0x0,
      beginIndex: GroveLib.Index(sha3(this, bytes32(id * 2))),
      endIndex: GroveLib.Index(sha3(this, bytes32(id * 2 + 1)))
    });
  }

  function add(List storage list, uint begin, uint end, uint intervalID) internal {
    var _intervalID = bytes32(intervalID);
    var _begin = _getBeginIndexKey(begin);
    var _end = _getEndIndexKey(end);

    list.beginIndex.insert(_intervalID, _begin);
    list.endIndex.insert(_intervalID, _end);
    list.length++;

    if (list.length == 1) {
      list.lowestBegin = list.beginIndex.root;
      list.highestEnd = list.endIndex.root;
      list.center = begin + (end - begin) / 2;

      return;
    }

    var newLowest = list.beginIndex.getPreviousNode(list.lowestBegin);
    if (newLowest != 0x0) {
      list.lowestBegin = newLowest;
    }

    var newHighest = list.endIndex.getNextNode(list.highestEnd);
    if (newHighest != 0x0) {
      list.highestEnd = newHighest;
    }
  }

  /*
   * @dev Searches interval list for:
   *   - matching intervals
   *   - information on how search should proceed
   * @param node The node to search
   * @param point The point to search for
   */
  function matching(List storage list, uint point)
    constant
    internal
    returns (uint[] memory intervalIDs, uint8 searchNext)
  {
    uint[] memory _intervalIDs = new uint[](list.length);
    uint num = 0;

    bytes32 cur;

    if (point == list.center) {
      /*
       * case: point exactly matches the list's center
       *
       * collect (all) matching intervals (every interval in list, by def)
       */
      cur = list.lowestBegin;
      while (cur != 0x0) {
	_intervalIDs[num] = uint(list.beginIndex.getNodeId(cur));
	num++;
	cur = _next(list, cur);
      }

      /*
       * search is done:
       * no other nodes in tree have intervals containing point
       */
      searchNext = SEARCH_DONE;
    } else if (point < list.center) {
      /*
       * case: point is earlier than center.
       *
       *
       * collect matching intervals.
       *
       * shortcut:
       *
       *   starting with lowest beginning interval, search sorted begin list
       *   until begin is later than point
       *
       *	       point
       *                 :
       *                 :   center
       *                 :     |
       *        (0) *----:-----|----------o
       *        (1)    *-:-----|---o
       *        (-)      x *---|------o
       *        (-)         *--|--o
       *        (-)          *-|----o
       *
       *
       *    this works because intervals contained in an interval list are
       *    guaranteed tocontain `center`
       */
      cur = list.lowestBegin;
      while (cur != 0x0) {
	uint begin = _begin(list, cur);
	if (begin > point) {
	  break;
	}

	_intervalIDs[num] = uint(list.beginIndex.getNodeId(cur));
	num++;

	cur = _next(list, cur);
      }

      /*
       * search should proceed to earlier
       */
      searchNext = SEARCH_EARLIER;
    } else if (point > list.center) {
      /*
       * case: point is later than center.
       *
       *
       * collect matching intervals.
       *
       * shortcut:
       *
       *   starting with highest ending interval, search sorted end list
       *   until end is earlier than or equal to point
       *
       *			    point
       *			    :
       *                     center :
       *                       |    :
       *            *----------|----:-----o (0)
       *                   *---|----:-o     (1)
       *                     *-|----o	    (not matching, done.)
       *               *-------|---o	    (-)
       *                    *--|--o	    (-)
       *
       *
       *    this works because intervals contained in an interval list are
       *    guaranteed to contain `center`
       */
      cur = list.highestEnd;
      while (cur != 0x0) {
	uint end = _end(list, cur);
	if (end <= point) {
	  break;
	}

	_intervalIDs[num] = uint(list.endIndex.getNodeId(cur));
	num++;

	cur = _previous(list, cur);
      }

      /*
       * search proceeds to later intervals
       */
      searchNext = SEARCH_LATER;
    }

    /*
     * return correctly-sized array of intervalIDs
     */
    if (num == _intervalIDs.length) {
      intervalIDs = _intervalIDs;
    } else {
      intervalIDs = new uint[](num);
      for (uint i = 0; i < num; i++) {
	intervalIDs[i] = _intervalIDs[i];
      }
    }
  }

  /*
   * Grove linked list traversal
   */
  function _begin(List storage list, bytes32 indexNode) constant internal returns (uint) {
    return _getBegin(list.beginIndex.getNodeValue(indexNode));
  }

  function _end(List storage list, bytes32 indexNode) constant internal returns (uint) {
    return _getEnd(list.endIndex.getNodeValue(indexNode));
  }

  function _next(List storage list, bytes32 cur) constant internal returns (bytes32) {
    return list.beginIndex.getNextNode(cur);
  }

  function _previous(List storage list, bytes32 cur) constant internal returns (bytes32) {
    return list.endIndex.getPreviousNode(cur);
  }

  /*
   * uint / int conversions for Grove nodeIDs
   */
  function _getBeginIndexKey(uint begin) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(begin - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getEndIndexKey(uint end) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(end - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getBegin(int beginIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(beginIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }

  function _getEnd(int endIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(endIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }
}


closes #102

closes #102

pragma solidity ^0.4.18;

import "contracts/Library/ClaimLib.sol";
import "contracts/Library/ExecutionLib.sol";
import "contracts/Library/PaymentLib.sol";
import "contracts/Library/RequestMetaLib.sol";
import "contracts/Library/RequestScheduleLib.sol";

import "contracts/Library/MathLib.sol";
import "contracts/zeppelin/SafeMath.sol";

library RequestLib {
    using ClaimLib for ClaimLib.ClaimData;
    using ExecutionLib for ExecutionLib.ExecutionData;
    using PaymentLib for PaymentLib.PaymentData;
    using RequestMetaLib for RequestMetaLib.RequestMeta;
    using RequestScheduleLib for RequestScheduleLib.ExecutionWindow;
    using SafeMath for uint;

    /*
     *  This struct exists to circumvent an issue with returning multiple
     *  values from a library function.  I found through experimentation that I
     *  could not return more than 4 things from a library function, even if I
     *  put them in arrays. - Piper
     */
    struct SerializedRequest {
        address[6]  addressValues;
        bool[3]     boolValues;
        uint[15]    uintValues;
        uint8[1]    uint8Values;
    }

    struct Request {
        ExecutionLib.ExecutionData          txnData;
        RequestMetaLib.RequestMeta          meta;
        PaymentLib.PaymentData              paymentData;
        ClaimLib.ClaimData                  claimData;
        RequestScheduleLib.ExecutionWindow  schedule;
        SerializedRequest                   serializedValues;
    }

    enum AbortReason {
        WasCancelled,       //0
        AlreadyCalled,      //1
        BeforeCallWindow,   //2
        AfterCallWindow,    //3
        ReservedForClaimer, //4
        InsufficientGas,    //5
        MismatchGasPrice    //6
    }

    event Aborted(uint8 reason);
    event Cancelled(uint rewardPayment, uint measuredGasConsumption);
    event Claimed();
    event Executed(uint payment, uint donation, uint measuredGasConsumption);

    /**
     * @dev Validate the initialization parameters of a transaction request.
     */
    function validate(
        address[4]  _addressArgs,
        uint[12]    _uintArgs,
        bytes       _callData,
        uint        _endowment
    )
        public view returns (bool[6] isValid)
    {
        Request memory request;

        // callData is special.
        request.txnData.callData = _callData;

        // Address values
        request.claimData.claimedBy =               0x0;
        request.meta.createdBy =                    _addressArgs[0];
        request.meta.owner =                        _addressArgs[1];
        request.paymentData.donationBenefactor =    _addressArgs[2];
        request.paymentData.donationBenefactor =    0x0;
        request.txnData.toAddress =                 _addressArgs[3];

        // Boolean values
        request.meta.isCancelled =      false;
        request.meta.wasCalled =        false;
        request.meta.wasSuccessful =    false;

        // UInt values
        request.claimData.claimDeposit =        0;
        request.paymentData.donation =          _uintArgs[0];
        request.paymentData.payment =           _uintArgs[1];
        request.paymentData.donationOwed =      0;
        request.paymentData.paymentOwed =       0;
        request.schedule.claimWindowSize =      _uintArgs[2];
        request.schedule.freezePeriod =         _uintArgs[3];
        request.schedule.reservedWindowSize =   _uintArgs[4];
        // This must be capped at 1 or it throws an exception.
        request.schedule.temporalUnit =         RequestScheduleLib.TemporalUnit(MathLib.min(_uintArgs[5], 2));
        request.schedule.windowSize =           _uintArgs[6];
        request.schedule.windowStart =          _uintArgs[7];
        request.txnData.callGas =               _uintArgs[8];
        request.txnData.callValue =             _uintArgs[9];
        request.txnData.gasPrice =              _uintArgs[10];
        request.claimData.requiredDeposit =     _uintArgs[11];

        // Uint8 values
        request.claimData.paymentModifier = 0;

        // The order of these errors matters as it determines which
        // ValidationError event codes are logged when validation fails.
        isValid[0] = PaymentLib.validateEndowment(
            _endowment,
            request.paymentData.payment,
            request.paymentData.donation,
            request.txnData.callGas,
            request.txnData.callValue,
            request.txnData.gasPrice,
            _EXECUTION_GAS_OVERHEAD
        );
        isValid[1] = RequestScheduleLib.validateReservedWindowSize(
            request.schedule.reservedWindowSize,
            request.schedule.windowSize
        );
        isValid[2] = RequestScheduleLib.validateTemporalUnit(_uintArgs[5]);
        isValid[3] = RequestScheduleLib.validateWindowStart(
            request.schedule.temporalUnit,
            request.schedule.freezePeriod,
            request.schedule.windowStart
        );
        isValid[4] = ExecutionLib.validateCallGas(
            request.txnData.callGas,
            _EXECUTION_GAS_OVERHEAD
        );
        isValid[5] = ExecutionLib.validateToAddress(request.txnData.toAddress);

        return isValid;
    }

    /**
     * @dev Initialize a new Request.
     */
    function initialize(
        Request storage self,
        address[4]      _addressArgs,
        uint[12]        _uintArgs,
        bytes           _callData
    )
        public returns (bool initialized)
    {
        address[6] memory addressValues = [
            0x0,                // self.claimData.claimedBy
            _addressArgs[0],    // self.meta.createdBy
            _addressArgs[1],    // self.meta.owner
            _addressArgs[2],    // self.paymentData.donationBenefactor
            0x0,                // self.paymentData.paymentBenefactor
            _addressArgs[3]     // self.txnData.toAddress
        ];

        bool[3] memory boolValues = [false, false, false];

        uint[15] memory uintValues = [
            0,                  // self.claimData.claimDeposit
            _uintArgs[0],       // self.paymentData.donation
            0,                  // self.paymentData.donationOwed
            _uintArgs[1],       // self.paymentData.payment
            0,                  // self.paymentData.paymentOwed
            _uintArgs[2],       // self.schedule.claimWindowSize
            _uintArgs[3],       // self.schedule.freezePeriod
            _uintArgs[4],       // self.schedule.reservedWindowSize
            _uintArgs[5],       // self.schedule.temporalUnit
            _uintArgs[6],       // self.schedule.windowSize
            _uintArgs[7],       // self.schedule.windowStart
            _uintArgs[8],       // self.txnData.callGas
            _uintArgs[9],       // self.txnData.callValue
            _uintArgs[10],      // self.txnData.gasPrice
            _uintArgs[11]       // self.claimData.requiredDeposit
        ];

        uint8[1] memory uint8Values = [
            0
        ];

        require( deserialize(self, addressValues, boolValues, uintValues, uint8Values, _callData) );

        return true;
    }

    /*
     *  Returns the entire data structure of the Request in a *serialized*
     *  format.  This will be missing the `callData` which must be requested
     *  separately
     *
     *  Parameter order is alphabetical by type, then namespace, then name
     *
     *  NOTE: This exists because of an issue I ran into related to returning
     *  multiple values from a library function.  I found through
     *  experimentation that I was unable to return more than 4 things, even if
     *  I used the trick of returning arrays of items.
     */
    function serialize(Request storage self)
        internal returns (bool serialized)
    {
        // Address values
        self.serializedValues.addressValues[0] = self.claimData.claimedBy;
        self.serializedValues.addressValues[1] = self.meta.createdBy;
        self.serializedValues.addressValues[2] = self.meta.owner;
        self.serializedValues.addressValues[3] = self.paymentData.donationBenefactor;
        self.serializedValues.addressValues[4] = self.paymentData.paymentBenefactor;
        self.serializedValues.addressValues[5] = self.txnData.toAddress;

        // Boolean values
        self.serializedValues.boolValues[0] = self.meta.isCancelled;
        self.serializedValues.boolValues[1] = self.meta.wasCalled;
        self.serializedValues.boolValues[2] = self.meta.wasSuccessful;

        // UInt256 values
        self.serializedValues.uintValues[0] = self.claimData.claimDeposit;
        self.serializedValues.uintValues[1] = self.paymentData.donation;
        self.serializedValues.uintValues[2] = self.paymentData.donationOwed;
        self.serializedValues.uintValues[3] = self.paymentData.payment;
        self.serializedValues.uintValues[4] = self.paymentData.paymentOwed;
        self.serializedValues.uintValues[5] = self.schedule.claimWindowSize;
        self.serializedValues.uintValues[6] = self.schedule.freezePeriod;
        self.serializedValues.uintValues[7] = self.schedule.reservedWindowSize;
        self.serializedValues.uintValues[8] = uint(self.schedule.temporalUnit);
        self.serializedValues.uintValues[9] = self.schedule.windowSize;
        self.serializedValues.uintValues[10] = self.schedule.windowStart;
        self.serializedValues.uintValues[11] = self.txnData.callGas;
        self.serializedValues.uintValues[12] = self.txnData.callValue;
        self.serializedValues.uintValues[13] = self.txnData.gasPrice;
        self.serializedValues.uintValues[14] = self.claimData.requiredDeposit;

        // Uint8 values
        self.serializedValues.uint8Values[0] = self.claimData.paymentModifier;

        return true;
    }

    /**
     * @dev Populates a Request object from the full output of `serialize`.
     *
     *  Parameter order is alphabetical by type, then namespace, then name.
     */
    function deserialize(
        Request storage self,
        address[6]  _addressValues,
        bool[3]     _boolValues,
        uint[15]    _uintValues,
        uint8[1]    _uint8Values,
        bytes       _callData
    )
        internal returns (bool deserialized)
    {
        // callData is special.
        self.txnData.callData = _callData;

        // Address values
        self.claimData.claimedBy =              _addressValues[0];
        self.meta.createdBy =                   _addressValues[1];
        self.meta.owner =                       _addressValues[2];
        self.paymentData.donationBenefactor =   _addressValues[3];
        self.paymentData.paymentBenefactor =    _addressValues[4];
        self.txnData.toAddress =                _addressValues[5];

        // Boolean values
        self.meta.isCancelled =     _boolValues[0];
        self.meta.wasCalled =       _boolValues[1];
        self.meta.wasSuccessful =   _boolValues[2];

        // UInt values
        self.claimData.claimDeposit =       _uintValues[0];
        self.paymentData.donation =         _uintValues[1];
        self.paymentData.donationOwed =     _uintValues[2];
        self.paymentData.payment =          _uintValues[3];
        self.paymentData.paymentOwed =      _uintValues[4];
        self.schedule.claimWindowSize =     _uintValues[5];
        self.schedule.freezePeriod =        _uintValues[6];
        self.schedule.reservedWindowSize =  _uintValues[7];
        self.schedule.temporalUnit =        RequestScheduleLib.TemporalUnit(_uintValues[8]);
        self.schedule.windowSize =          _uintValues[9];
        self.schedule.windowStart =         _uintValues[10];
        self.txnData.callGas =              _uintValues[11];
        self.txnData.callValue =            _uintValues[12];
        self.txnData.gasPrice =             _uintValues[13];
        self.claimData.requiredDeposit =    _uintValues[14];

        // Uint8 values
        self.claimData.paymentModifier = _uint8Values[0];

        deserialized = true;
    }

    function execute(Request storage self)
        internal returns (bool)
    {
        /*
         *  Execute the TransactionRequest
         *
         *  +---------------------+
         *  | Phase 1: Validation |
         *  +---------------------+
         *
         *  Must pass all of the following checks:
         *
         *  1. Not already called.
         *  2. Not cancelled.
         *  3. Not before the execution window.
         *  4. Not after the execution window.
         *  5. if (claimedBy == 0x0 or msg.sender == claimedBy):
         *         - windowStart <= block.number
         *         - block.number <= windowStart + windowSize
         *     else if (msg.sender != claimedBy):
         *         - windowStart + reservedWindowSize <= block.number
         *         - block.number <= windowStart + windowSize
         *     else:
         *         - throw (should be impossible)
         *
         *  6. msg.gas == callGas
         *
         *  +--------------------+
         *  | Phase 2: Execution |
         *  +--------------------+
         *
         *  1. Mark as called (must be before actual execution to prevent
         *     re-entrance)
         *  2. Send Transaction and record success or failure.
         *
         *  +---------------------+
         *  | Phase 3: Accounting |
         *  +---------------------+
         *
         *  1. Calculate and send donation amount.
         *  2. Calculate and send payment amount.
         *  3. Send remaining ether back to owner.
         *
         */

        uint startGas = msg.gas;

        // +----------------------+
        // | Begin: Authorization |
        // +----------------------+

        if (msg.gas < requiredExecutionGas(self).sub(_PRE_EXECUTION_GAS)) {
            Aborted(uint8(AbortReason.InsufficientGas));
            return false;
        } else if (self.meta.wasCalled) {
            Aborted(uint8(AbortReason.AlreadyCalled));
            return false;
        } else if (self.meta.isCancelled) {
            Aborted(uint8(AbortReason.WasCancelled));
            return false;
        } else if (self.schedule.isBeforeWindow()) {
            Aborted(uint8(AbortReason.BeforeCallWindow));
            return false;
        } else if (self.schedule.isAfterWindow()) {
            Aborted(uint8(AbortReason.AfterCallWindow));
            return false;
        } else if (self.claimData.isClaimed() &&
                   msg.sender != self.claimData.claimedBy &&
                   self.schedule.inReservedWindow()) {
            Aborted(uint8(AbortReason.ReservedForClaimer));
            return false;
        } else if (self.txnData.gasPrice != tx.gasprice) {
            Aborted(uint8(AbortReason.MismatchGasPrice));
            return false;
        }

        // +--------------------+
        // | End: Authorization |
        // +--------------------+
        // +------------------+
        // | Begin: Execution |
        // +------------------+

        /// Mark as being called before sending transaction to prevent re-entrance.
        self.meta.wasCalled = true;

        /// Send the transaction...
        /// The transaction is allowed to fail and the caller will still get paid.
        self.meta.wasSuccessful = self.txnData.sendTransaction();

        // +----------------+
        // | End: Execution |
        // +----------------+
        // +-------------------+
        // | Begin: Accounting |
        // +-------------------+

        // Compute the donation amount
        if (self.paymentData.hasBenefactor()) {
            self.paymentData.donationOwed = self.paymentData.getDonation()
                                                            .add(self.paymentData.donationOwed);
        }

        // record this so that we can log it later.
        uint totalDonationPayment = self.paymentData.donationOwed;

        // Send the donation.
        self.paymentData.sendDonation();

        // Compute the payment amount and who it should be sent do.
        self.paymentData.paymentBenefactor = msg.sender;
        if (self.claimData.isClaimed()) {
            self.paymentData.paymentOwed = self.claimData.claimDeposit.add(self.paymentData.paymentOwed);
            // need to zero out the claim deposit since it is now accounted for
            // in the paymentOwed value.
            self.claimData.claimDeposit = 0;
            self.paymentData.paymentOwed = self.paymentData.getPaymentWithModifier(self.claimData.paymentModifier)
                                                           .add(self.paymentData.paymentOwed);
        } else {
            self.paymentData.paymentOwed = self.paymentData.getPayment()
                                                           .add(self.paymentData.paymentOwed);
        }

        // Record the amount of gas used by execution.
        uint measuredGasConsumption = startGas.sub(msg.gas).add(_EXECUTE_EXTRA_GAS);

        // // +----------------------------------------------------------------------+
        // // | NOTE: All code after this must be accounted for by EXECUTE_EXTRA_GAS |
        // // +----------------------------------------------------------------------+

        // Add the gas reimbursment amount to the payment.
        self.paymentData.paymentOwed = measuredGasConsumption.mul(tx.gasprice)
                                                             .add(self.paymentData.paymentOwed);

        // Log the two payment amounts.  Otherwise it is non-trivial to figure
        // out how much was payed.
        Executed(self.paymentData.paymentOwed,
                 totalDonationPayment,
                 measuredGasConsumption);

        // Attempt to send the payment. This is allowed to fail so it may need to be called again.
        self.paymentData.sendPayment();

        // Send all extra ether back to the owner.
        _sendOwnerEther(self);

        // +-----------------+
        // | End: Accounting |
        // +-----------------+
        return true;
    }

    // This is the amount of gas that it takes to enter from the
    // `TransactionRequest.execute()` contract into the `RequestLib.execute()`
    // method at the point where the gas check happens.
    uint private constant _PRE_EXECUTION_GAS = 25000;   // TODO is this number still accurate?

    function PRE_EXECUTION_GAS()
        public pure returns (uint)
    {
        return _PRE_EXECUTION_GAS;
    }

    function requiredExecutionGas(Request storage self)
        public view returns (uint requiredGas)
    {
        requiredGas = self.txnData.callGas.add(_EXECUTION_GAS_OVERHEAD);
    }

    /*
     * The amount of gas needed to complete the execute method after
     * the transaction has been sent.
     */
    uint private constant _EXECUTION_GAS_OVERHEAD = 180000; // TODO check accuracy of this number

    function EXECUTION_GAS_OVERHEAD()
        public pure returns (uint)
    {
        return _EXECUTION_GAS_OVERHEAD;
    }

    /*
     *  The amount of gas used by the portion of the `execute` function
     *  that cannot be accounted for via gas tracking.
     */
    uint private constant  _EXECUTE_EXTRA_GAS = 90000; // again, check for accuracy... Doubled this from Piper's original - Logan

    function EXECUTE_EXTRA_GAS()
        public pure returns (uint)
    {
        return _EXECUTE_EXTRA_GAS;
    }

    /*
     * @dev Performs the checks to see if a request can be cancelled.
     *  Must satisfy the following conditions.
     *
     *  1. Not Cancelled
     *  2. either:
     *    * not wasCalled && afterExecutionWindow
     *    * not claimed && beforeFreezeWindow && msg.sender == owner
     */
    function isCancellable(Request storage self)
        internal view returns (bool)
    {
        if (self.meta.isCancelled) {
            // already cancelled!
            return false;
        } else if (!self.meta.wasCalled && self.schedule.isAfterWindow()) {
            // not called but after the window
            return true;
        } else if (!self.claimData.isClaimed() && self.schedule.isBeforeFreeze() && msg.sender == self.meta.owner) {
            // not claimed and before freezePeriod and owner is cancelling
            return true;
        } else {
            // otherwise cannot cancel
            return false;
        }
    }

    /*
     *  Constant value to account for the gas usage that cannot be accounted
     *  for using gas-tracking within the `cancel` function.
     */
    uint private constant _CANCEL_EXTRA_GAS = 85000; // Check accuracy

    function CANCEL_EXTRA_GAS()
        public pure returns (uint)
    {
        return _CANCEL_EXTRA_GAS;
    }

    /*
     *  Cancel the transaction request, attempting to send all appropriate
     *  refunds.  To incentivise cancellation by other parties, a small reward
     *  payment is issued to the party that cancels the request if they are not
     *  the owner.
     */
    function cancel(Request storage self)
        public returns (bool)
    {
        uint startGas = msg.gas;
        uint rewardPayment;
        uint measuredGasConsumption;

        /// Checks if this transactionRequest can be cancelled.
        require( isCancellable(self) );

        /// Set here to prevent re-entrance attacks.
        self.meta.isCancelled = true;

        /// Refund the claim deposit (if there is one)
        require( self.claimData.refundDeposit() );

        /// Send a reward to the canceller if they are not the owner.
        /// This is to incentivize the cancelling of expired transactionRequests.
        // This also guarantees that it is being cancelled after the call window
        // since the `isCancellable()` function checks this.
        if (msg.sender != self.meta.owner) {
            /// Create the rewardBenefactor
            address rewardBenefactor = msg.sender;
            /// Create the rewardOwed variable, it is one-hundredth
            /// of the payment.
            uint rewardOwed = self.paymentData.paymentOwed.add(
                self.paymentData.payment.div(100)
            );

            /// Calc the amount of gas caller used to call this function.
            measuredGasConsumption = startGas.sub(msg.gas).add(_CANCEL_EXTRA_GAS);
            /// Add their gas fees to the reward.
            rewardOwed = measuredGasConsumption.mul(tx.gasprice).add(rewardOwed);

            /// Take note of the rewardPayment to log it.
            rewardPayment = rewardOwed;

            /// Transfers the rewardPayment.
            if (rewardOwed > 0) {
                self.paymentData.paymentOwed = 0;
                rewardBenefactor.transfer(rewardOwed);
            }
        }

        /// Logs are our friends.
        Cancelled(rewardPayment, measuredGasConsumption);

        // send the remaining ether to the owner.
        return sendOwnerEther(self);
        // return true;
    }

    /*
     * @dev Performs the checks to verify that a request is claimable.
     * @param self The Request object.
     */
    function isClaimable(Request storage self)
        internal view returns (bool)
    {
        /// Require not claimed and not cancelled.
        require( !self.claimData.isClaimed() );
        require( !self.meta.isCancelled );

        // Require that it's in the claim window and the value sent is over the min deposit.
        require( self.schedule.inClaimWindow() );
        require( msg.value >= self.claimData.requiredDeposit );
        return true;
    }

    /*
     * @dev Claims the request.
     * @param self The Request object.
     * Payable because it requires the sender to send enough ether to cover the claimDeposit.
     */
    function claim(Request storage self)
        internal returns (bool claimed)
    {
        require( isClaimable(self) );

        self.claimData.claim(self.schedule.computePaymentModifier());
        Claimed();
        claimed = true;
    }

    /*
     * @dev Refund claimer deposit.
     */
    function refundClaimDeposit(Request storage self)
        public returns (bool)
    {
        require( self.meta.isCancelled || self.schedule.isAfterWindow() );
        return self.claimData.refundDeposit();
    }

    /*
     * Send donation
     */
    function sendDonation(Request storage self)
        public returns (bool)
    {
        if (self.schedule.isAfterWindow()) {
            return self.paymentData.sendDonation();
        }
        return false;
    }

    /*
     * Send payment
     */
    function sendPayment(Request storage self)
        public returns (bool)
    {
        /// check wasCalled
        if (self.schedule.isAfterWindow()) {
            return self.paymentData.sendPayment();
        }
        return false;
    }

    function sendOwnerEther(Request storage self)
        public returns (bool)
    {
        if( self.meta.isCancelled || self.schedule.isAfterWindow() ) {
            return _sendOwnerEther(self);
        }
        return false;
    }

    function _sendOwnerEther(Request storage self)
        internal returns (bool)
    {
        // Note! This does not do any checks since it is used in the execute function.
        // The public version of the function should be used for checks and in the cancel function.
        uint ownerRefund = this.balance.sub(self.claimData.claimDeposit)
                                        .sub(self.paymentData.paymentOwed)
                                        .sub(self.paymentData.donationOwed);
        return self.meta.owner.send(ownerRefund);
    }
}

pragma solidity ^0.4.18;

import "contracts/Library/ClaimLib.sol";
import "contracts/Library/ExecutionLib.sol";
import "contracts/Library/PaymentLib.sol";
import "contracts/Library/RequestMetaLib.sol";
import "contracts/Library/RequestScheduleLib.sol";

import "contracts/Library/MathLib.sol";
import "contracts/zeppelin/SafeMath.sol";

library RequestLib {
    using ClaimLib for ClaimLib.ClaimData;
    using ExecutionLib for ExecutionLib.ExecutionData;
    using PaymentLib for PaymentLib.PaymentData;
    using RequestMetaLib for RequestMetaLib.RequestMeta;
    using RequestScheduleLib for RequestScheduleLib.ExecutionWindow;
    using SafeMath for uint;

    /*
     *  This struct exists to circumvent an issue with returning multiple
     *  values from a library function.  I found through experimentation that I
     *  could not return more than 4 things from a library function, even if I
     *  put them in arrays. - Piper
     */
    struct SerializedRequest {
        address[6]  addressValues;
        bool[3]     boolValues;
        uint[15]    uintValues;
        uint8[1]    uint8Values;
    }

    struct Request {
        ExecutionLib.ExecutionData          txnData;
        RequestMetaLib.RequestMeta          meta;
        PaymentLib.PaymentData              paymentData;
        ClaimLib.ClaimData                  claimData;
        RequestScheduleLib.ExecutionWindow  schedule;
        SerializedRequest                   serializedValues;
    }

    enum AbortReason {
        WasCancelled,       //0
        AlreadyCalled,      //1
        BeforeCallWindow,   //2
        AfterCallWindow,    //3
        ReservedForClaimer, //4
        InsufficientGas,    //5
        MismatchGasPrice    //6
    }

    event Aborted(uint8 reason);
    event Cancelled(uint rewardPayment, uint measuredGasConsumption);
    event Claimed();
    event Executed(uint payment, uint donation, uint measuredGasConsumption);

    /**
     * @dev Validate the initialization parameters of a transaction request.
     */
    function validate(
        address[4]  _addressArgs,
        uint[12]    _uintArgs,
        bytes       _callData,
        uint        _endowment
    )
        public view returns (bool[6] isValid)
    {
        Request memory request;

        // callData is special.
        request.txnData.callData = _callData;

        // Address values
        request.claimData.claimedBy =               0x0;
        request.meta.createdBy =                    _addressArgs[0];
        request.meta.owner =                        _addressArgs[1];
        request.paymentData.donationBenefactor =    _addressArgs[2];
        request.paymentData.donationBenefactor =    0x0;
        request.txnData.toAddress =                 _addressArgs[3];

        // Boolean values
        request.meta.isCancelled =      false;
        request.meta.wasCalled =        false;
        request.meta.wasSuccessful =    false;

        // UInt values
        request.claimData.claimDeposit =        0;
        request.paymentData.donation =          _uintArgs[0];
        request.paymentData.payment =           _uintArgs[1];
        request.paymentData.donationOwed =      0;
        request.paymentData.paymentOwed =       0;
        request.schedule.claimWindowSize =      _uintArgs[2];
        request.schedule.freezePeriod =         _uintArgs[3];
        request.schedule.reservedWindowSize =   _uintArgs[4];
        // This must be capped at 1 or it throws an exception.
        request.schedule.temporalUnit =         RequestScheduleLib.TemporalUnit(MathLib.min(_uintArgs[5], 2));
        request.schedule.windowSize =           _uintArgs[6];
        request.schedule.windowStart =          _uintArgs[7];
        request.txnData.callGas =               _uintArgs[8];
        request.txnData.callValue =             _uintArgs[9];
        request.txnData.gasPrice =              _uintArgs[10];
        request.claimData.requiredDeposit =     _uintArgs[11];

        // Uint8 values
        request.claimData.paymentModifier = 0;

        // The order of these errors matters as it determines which
        // ValidationError event codes are logged when validation fails.
        isValid[0] = PaymentLib.validateEndowment(
            _endowment,
            request.paymentData.payment,
            request.paymentData.donation,
            request.txnData.callGas,
            request.txnData.callValue,
            request.txnData.gasPrice,
            _EXECUTION_GAS_OVERHEAD
        );
        isValid[1] = RequestScheduleLib.validateReservedWindowSize(
            request.schedule.reservedWindowSize,
            request.schedule.windowSize
        );
        isValid[2] = RequestScheduleLib.validateTemporalUnit(_uintArgs[5]);
        isValid[3] = RequestScheduleLib.validateWindowStart(
            request.schedule.temporalUnit,
            request.schedule.freezePeriod,
            request.schedule.windowStart
        );
        isValid[4] = ExecutionLib.validateCallGas(
            request.txnData.callGas,
            _EXECUTION_GAS_OVERHEAD
        );
        isValid[5] = ExecutionLib.validateToAddress(request.txnData.toAddress);

        return isValid;
    }

    /**
     * @dev Initialize a new Request.
     */
    function initialize(
        Request storage self,
        address[4]      _addressArgs,
        uint[12]        _uintArgs,
        bytes           _callData
    )
        public returns (bool initialized)
    {
        address[6] memory addressValues = [
            0x0,                // self.claimData.claimedBy
            _addressArgs[0],    // self.meta.createdBy
            _addressArgs[1],    // self.meta.owner
            _addressArgs[2],    // self.paymentData.donationBenefactor
            0x0,                // self.paymentData.paymentBenefactor
            _addressArgs[3]     // self.txnData.toAddress
        ];

        bool[3] memory boolValues = [false, false, false];

        uint[15] memory uintValues = [
            0,                  // self.claimData.claimDeposit
            _uintArgs[0],       // self.paymentData.donation
            0,                  // self.paymentData.donationOwed
            _uintArgs[1],       // self.paymentData.payment
            0,                  // self.paymentData.paymentOwed
            _uintArgs[2],       // self.schedule.claimWindowSize
            _uintArgs[3],       // self.schedule.freezePeriod
            _uintArgs[4],       // self.schedule.reservedWindowSize
            _uintArgs[5],       // self.schedule.temporalUnit
            _uintArgs[6],       // self.schedule.windowSize
            _uintArgs[7],       // self.schedule.windowStart
            _uintArgs[8],       // self.txnData.callGas
            _uintArgs[9],       // self.txnData.callValue
            _uintArgs[10],      // self.txnData.gasPrice
            _uintArgs[11]       // self.claimData.requiredDeposit
        ];

        uint8[1] memory uint8Values = [
            0
        ];

        require( deserialize(self, addressValues, boolValues, uintValues, uint8Values, _callData) );

        return true;
    }

    /*
     *  Returns the entire data structure of the Request in a *serialized*
     *  format.  This will be missing the `callData` which must be requested
     *  separately
     *
     *  Parameter order is alphabetical by type, then namespace, then name
     *
     *  NOTE: This exists because of an issue I ran into related to returning
     *  multiple values from a library function.  I found through
     *  experimentation that I was unable to return more than 4 things, even if
     *  I used the trick of returning arrays of items.
     */
    function serialize(Request storage self)
        internal returns (bool serialized)
    {
        // Address values
        self.serializedValues.addressValues[0] = self.claimData.claimedBy;
        self.serializedValues.addressValues[1] = self.meta.createdBy;
        self.serializedValues.addressValues[2] = self.meta.owner;
        self.serializedValues.addressValues[3] = self.paymentData.donationBenefactor;
        self.serializedValues.addressValues[4] = self.paymentData.paymentBenefactor;
        self.serializedValues.addressValues[5] = self.txnData.toAddress;

        // Boolean values
        self.serializedValues.boolValues[0] = self.meta.isCancelled;
        self.serializedValues.boolValues[1] = self.meta.wasCalled;
        self.serializedValues.boolValues[2] = self.meta.wasSuccessful;

        // UInt256 values
        self.serializedValues.uintValues[0] = self.claimData.claimDeposit;
        self.serializedValues.uintValues[1] = self.paymentData.donation;
        self.serializedValues.uintValues[2] = self.paymentData.donationOwed;
        self.serializedValues.uintValues[3] = self.paymentData.payment;
        self.serializedValues.uintValues[4] = self.paymentData.paymentOwed;
        self.serializedValues.uintValues[5] = self.schedule.claimWindowSize;
        self.serializedValues.uintValues[6] = self.schedule.freezePeriod;
        self.serializedValues.uintValues[7] = self.schedule.reservedWindowSize;
        self.serializedValues.uintValues[8] = uint(self.schedule.temporalUnit);
        self.serializedValues.uintValues[9] = self.schedule.windowSize;
        self.serializedValues.uintValues[10] = self.schedule.windowStart;
        self.serializedValues.uintValues[11] = self.txnData.callGas;
        self.serializedValues.uintValues[12] = self.txnData.callValue;
        self.serializedValues.uintValues[13] = self.txnData.gasPrice;
        self.serializedValues.uintValues[14] = self.claimData.requiredDeposit;

        // Uint8 values
        self.serializedValues.uint8Values[0] = self.claimData.paymentModifier;

        return true;
    }

    /**
     * @dev Populates a Request object from the full output of `serialize`.
     *
     *  Parameter order is alphabetical by type, then namespace, then name.
     */
    function deserialize(
        Request storage self,
        address[6]  _addressValues,
        bool[3]     _boolValues,
        uint[15]    _uintValues,
        uint8[1]    _uint8Values,
        bytes       _callData
    )
        internal returns (bool deserialized)
    {
        // callData is special.
        self.txnData.callData = _callData;

        // Address values
        self.claimData.claimedBy =              _addressValues[0];
        self.meta.createdBy =                   _addressValues[1];
        self.meta.owner =                       _addressValues[2];
        self.paymentData.donationBenefactor =   _addressValues[3];
        self.paymentData.paymentBenefactor =    _addressValues[4];
        self.txnData.toAddress =                _addressValues[5];

        // Boolean values
        self.meta.isCancelled =     _boolValues[0];
        self.meta.wasCalled =       _boolValues[1];
        self.meta.wasSuccessful =   _boolValues[2];

        // UInt values
        self.claimData.claimDeposit =       _uintValues[0];
        self.paymentData.donation =         _uintValues[1];
        self.paymentData.donationOwed =     _uintValues[2];
        self.paymentData.payment =          _uintValues[3];
        self.paymentData.paymentOwed =      _uintValues[4];
        self.schedule.claimWindowSize =     _uintValues[5];
        self.schedule.freezePeriod =        _uintValues[6];
        self.schedule.reservedWindowSize =  _uintValues[7];
        self.schedule.temporalUnit =        RequestScheduleLib.TemporalUnit(_uintValues[8]);
        self.schedule.windowSize =          _uintValues[9];
        self.schedule.windowStart =         _uintValues[10];
        self.txnData.callGas =              _uintValues[11];
        self.txnData.callValue =            _uintValues[12];
        self.txnData.gasPrice =             _uintValues[13];
        self.claimData.requiredDeposit =    _uintValues[14];

        // Uint8 values
        self.claimData.paymentModifier = _uint8Values[0];

        deserialized = true;
    }

    function execute(Request storage self)
        internal returns (bool)
    {
        /*
         *  Execute the TransactionRequest
         *
         *  +---------------------+
         *  | Phase 1: Validation |
         *  +---------------------+
         *
         *  Must pass all of the following checks:
         *
         *  1. Not already called.
         *  2. Not cancelled.
         *  3. Not before the execution window.
         *  4. Not after the execution window.
         *  5. if (claimedBy == 0x0 or msg.sender == claimedBy):
         *         - windowStart <= block.number
         *         - block.number <= windowStart + windowSize
         *     else if (msg.sender != claimedBy):
         *         - windowStart + reservedWindowSize <= block.number
         *         - block.number <= windowStart + windowSize
         *     else:
         *         - throw (should be impossible)
         *
         *  6. msg.gas == callGas
         *
         *  +--------------------+
         *  | Phase 2: Execution |
         *  +--------------------+
         *
         *  1. Mark as called (must be before actual execution to prevent
         *     re-entrance)
         *  2. Send Transaction and record success or failure.
         *
         *  +---------------------+
         *  | Phase 3: Accounting |
         *  +---------------------+
         *
         *  1. Calculate and send donation amount.
         *  2. Calculate and send payment amount.
         *  3. Send remaining ether back to owner.
         *
         */

        uint startGas = msg.gas;

        // +----------------------+
        // | Begin: Authorization |
        // +----------------------+

        if (msg.gas < requiredExecutionGas(self).sub(_PRE_EXECUTION_GAS)) {
            Aborted(uint8(AbortReason.InsufficientGas));
            return false;
        } else if (self.meta.wasCalled) {
            Aborted(uint8(AbortReason.AlreadyCalled));
            return false;
        } else if (self.meta.isCancelled) {
            Aborted(uint8(AbortReason.WasCancelled));
            return false;
        } else if (self.schedule.isBeforeWindow()) {
            Aborted(uint8(AbortReason.BeforeCallWindow));
            return false;
        } else if (self.schedule.isAfterWindow()) {
            Aborted(uint8(AbortReason.AfterCallWindow));
            return false;
        } else if (self.claimData.isClaimed() &&
                   msg.sender != self.claimData.claimedBy &&
                   self.schedule.inReservedWindow()) {
            Aborted(uint8(AbortReason.ReservedForClaimer));
            return false;
        } else if (self.txnData.gasPrice != tx.gasprice) {
            Aborted(uint8(AbortReason.MismatchGasPrice));
            return false;
        }

        // +--------------------+
        // | End: Authorization |
        // +--------------------+
        // +------------------+
        // | Begin: Execution |
        // +------------------+

        /// Mark as being called before sending transaction to prevent re-entrance.
        self.meta.wasCalled = true;

        /// Send the transaction...
        /// The transaction is allowed to fail and the caller will still get paid.
        self.meta.wasSuccessful = self.txnData.sendTransaction();

        // +----------------+
        // | End: Execution |
        // +----------------+
        // +-------------------+
        // | Begin: Accounting |
        // +-------------------+

        // Compute the donation amount
        if (self.paymentData.hasBenefactor()) {
            self.paymentData.donationOwed = self.paymentData.getDonation()
                                                            .add(self.paymentData.donationOwed);
        }

        // record this so that we can log it later.
        uint totalDonationPayment = self.paymentData.donationOwed;

        // Send the donation.
        self.paymentData.sendDonation();

        // Compute the payment amount and who it should be sent do.
        self.paymentData.paymentBenefactor = msg.sender;
        if (self.claimData.isClaimed()) {
            self.paymentData.paymentOwed = self.claimData.claimDeposit.add(self.paymentData.paymentOwed);
            // need to zero out the claim deposit since it is now accounted for
            // in the paymentOwed value.
            self.claimData.claimDeposit = 0;
            self.paymentData.paymentOwed = self.paymentData.getPaymentWithModifier(self.claimData.paymentModifier)
                                                           .add(self.paymentData.paymentOwed);
        } else {
            self.paymentData.paymentOwed = self.paymentData.getPayment()
                                                           .add(self.paymentData.paymentOwed);
        }

        // Record the amount of gas used by execution.
        uint measuredGasConsumption = startGas.sub(msg.gas).add(_EXECUTE_EXTRA_GAS);

        // // +----------------------------------------------------------------------+
        // // | NOTE: All code after this must be accounted for by EXECUTE_EXTRA_GAS |
        // // +----------------------------------------------------------------------+

        // Add the gas reimbursment amount to the payment.
        self.paymentData.paymentOwed = measuredGasConsumption.mul(tx.gasprice)
                                                             .add(self.paymentData.paymentOwed);

        // Log the two payment amounts.  Otherwise it is non-trivial to figure
        // out how much was payed.
        Executed(self.paymentData.paymentOwed,
                 totalDonationPayment,
                 measuredGasConsumption);

        // Attempt to send the payment. This is allowed to fail so it may need to be called again.
        self.paymentData.sendPayment();

        // Send all extra ether back to the owner.
        _sendOwnerEther(self);

        // +-----------------+
        // | End: Accounting |
        // +-----------------+
        return true;
    }

    // This is the amount of gas that it takes to enter from the
    // `TransactionRequest.execute()` contract into the `RequestLib.execute()`
    // method at the point where the gas check happens.
    uint private constant _PRE_EXECUTION_GAS = 25000;   // TODO is this number still accurate?

    function PRE_EXECUTION_GAS()
        public pure returns (uint)
    {
        return _PRE_EXECUTION_GAS;
    }

    function requiredExecutionGas(Request storage self)
        public view returns (uint requiredGas)
    {
        requiredGas = self.txnData.callGas.add(_EXECUTION_GAS_OVERHEAD);
    }

    /*
     * The amount of gas needed to complete the execute method after
     * the transaction has been sent.
     */
    uint private constant _EXECUTION_GAS_OVERHEAD = 180000; // TODO check accuracy of this number

    function EXECUTION_GAS_OVERHEAD()
        public pure returns (uint)
    {
        return _EXECUTION_GAS_OVERHEAD;
    }

    /*
     *  The amount of gas used by the portion of the `execute` function
     *  that cannot be accounted for via gas tracking.
     */
    uint private constant  _EXECUTE_EXTRA_GAS = 90000; // again, check for accuracy... Doubled this from Piper's original - Logan

    function EXECUTE_EXTRA_GAS()
        public pure returns (uint)
    {
        return _EXECUTE_EXTRA_GAS;
    }

    /*
     * @dev Performs the checks to see if a request can be cancelled.
     *  Must satisfy the following conditions.
     *
     *  1. Not Cancelled
     *  2. either:
     *    * not wasCalled && afterExecutionWindow
     *    * not claimed && beforeFreezeWindow && msg.sender == owner
     */
    function isCancellable(Request storage self)
        internal view returns (bool)
    {
        if (self.meta.isCancelled) {
            // already cancelled!
            return false;
        } else if (!self.meta.wasCalled && self.schedule.isAfterWindow()) {
            // not called but after the window
            return true;
        } else if (!self.claimData.isClaimed() && self.schedule.isBeforeFreeze() && msg.sender == self.meta.owner) {
            // not claimed and before freezePeriod and owner is cancelling
            return true;
        } else {
            // otherwise cannot cancel
            return false;
        }
    }

    /*
     *  Constant value to account for the gas usage that cannot be accounted
     *  for using gas-tracking within the `cancel` function.
     */
    uint private constant _CANCEL_EXTRA_GAS = 85000; // Check accuracy

    function CANCEL_EXTRA_GAS()
        public pure returns (uint)
    {
        return _CANCEL_EXTRA_GAS;
    }

    /*
     *  Cancel the transaction request, attempting to send all appropriate
     *  refunds.  To incentivise cancellation by other parties, a small reward
     *  payment is issued to the party that cancels the request if they are not
     *  the owner.
     */
    function cancel(Request storage self)
        public returns (bool)
    {
        uint startGas = msg.gas;
        uint rewardPayment;
        uint measuredGasConsumption;

        /// Checks if this transactionRequest can be cancelled.
        require( isCancellable(self) );

        /// Set here to prevent re-entrance attacks.
        self.meta.isCancelled = true;

        /// Refund the claim deposit (if there is one)
        require( self.claimData.refundDeposit() );

        /// Send a reward to the canceller if they are not the owner.
        /// This is to incentivize the cancelling of expired transactionRequests.
        // This also guarantees that it is being cancelled after the call window
        // since the `isCancellable()` function checks this.
        if (msg.sender != self.meta.owner) {
            /// Create the rewardBenefactor
            address rewardBenefactor = msg.sender;
            /// Create the rewardOwed variable, it is one-hundredth
            /// of the payment.
            uint rewardOwed = self.paymentData.paymentOwed.add(
                self.paymentData.payment.div(100)
            );

            /// Calc the amount of gas caller used to call this function.
            measuredGasConsumption = startGas.sub(msg.gas).add(_CANCEL_EXTRA_GAS);
            /// Add their gas fees to the reward.
            rewardOwed = measuredGasConsumption.mul(tx.gasprice).add(rewardOwed);

            /// Take note of the rewardPayment to log it.
            rewardPayment = rewardOwed;

            /// Transfers the rewardPayment.
            if (rewardOwed > 0) { // ? - will it ever not be above zero?
                self.paymentData.paymentOwed = 0;
                rewardBenefactor.transfer(rewardOwed);
            }
        }

        /// Logs are our friends.
        Cancelled(rewardPayment, measuredGasConsumption);

        // send the remaining ether to the owner.
        return sendOwnerEther(self);
        // return true;
    }

    /*
     * @dev Performs the checks to verify that a request is claimable.
     * @param self The Request object.
     */
    function isClaimable(Request storage self)
        internal view returns (bool)
    {
        /// Require not claimed and not cancelled.
        require( !self.claimData.isClaimed() );
        require( !self.meta.isCancelled );

        // Require that it's in the claim window and the value sent is over the min deposit.
        require( self.schedule.inClaimWindow() );
        require( msg.value >= self.claimData.requiredDeposit );
        return true;
    }

    /*
     * @dev Claims the request.
     * @param self The Request object.
     * Payable because it requires the sender to send enough ether to cover the claimDeposit.
     */
    function claim(Request storage self)
        internal returns (bool claimed)
    {
        require( isClaimable(self) );

        self.claimData.claim(self.schedule.computePaymentModifier());
        Claimed();
        claimed = true;
    }

    /*
     * @dev Refund claimer deposit.
     */
    function refundClaimDeposit(Request storage self)
        public returns (bool)
    {
        require( self.meta.isCancelled || self.schedule.isAfterWindow() );
        return self.claimData.refundDeposit();
    }

    /*
     * Send donation
     */
    function sendDonation(Request storage self)
        public returns (bool)
    {
        if (self.schedule.isAfterWindow()) {
            return self.paymentData.sendDonation();
        }
        return false;
    }

    /*
     * Send payment
     */
    function sendPayment(Request storage self)
        public returns (bool)
    {
        /// check wasCalled
        if (self.schedule.isAfterWindow()) {
            return self.paymentData.sendPayment();
        }
        return false;
    }

    function sendOwnerEther(Request storage self)
        public returns (bool)
    {
        if( self.meta.isCancelled || self.schedule.isAfterWindow() ) {
            return _sendOwnerEther(self);
        }
        return false;
    }

    function _sendOwnerEther(Request storage self)
        internal returns (bool)
    {
        // Note! This does not do any checks since it is used in the execute function.
        // The public version of the function should be used for checks and in the cancel function.
        uint ownerRefund = this.balance.sub(self.claimData.claimDeposit)
                                        .sub(self.paymentData.paymentOwed)
                                        .sub(self.paymentData.donationOwed);
        return self.meta.owner.send(ownerRefund);
    }
}


:middle-finger: for LuKa fix

:middle-finger: for LuKa fix

pragma solidity ^0.4.4;

contract BalanceBook{
	struct Payment{
		int encrypted_change;
		bool active;
	}

	mapping (uint => address) coaches;
	mapping (uint => mapping (string => Payment)) private payments;
	mapping (uint => uint) public public_ns;
	mapping (uint => uint) public public_gs;
	address public owner;

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

	modifier onlyCoach(uint household) {
		if (msg.sender == coaches[household]) {
			_;
		}
	}

	function addHouseHold(uint household, uint n, uint g) {
		coaches[household] = msg.sender;
		public_ns[household] = n * n;
		public_gs[household] = g;
	}

	function removeHouseHold(uint household) onlyCoach(household) {
		delete coaches[household];
		delete public_ns[household];
		delete public_gs[household];
	}

	function addPayment(uint household, string company, int encrypted_change, bool active) onlyCoach(household) {
		Payment memory payment = Payment(encrypted_change, active);
		payments[household][company] = payment;
	}

	function togglePayment(uint household, string company) onlyCoach(household) {
		payments[household][company].active = !payments[household][company].active;
	}

	function getPayment(uint household, string company) returns (int, bool) {
	    Payment payment = payments[household][company];
	    return (payment.encrypted_change, payment.active);
	}

	function getPublicKeys(uint household) returns (uint, uint) {
		return (public_ns[household], public_gs[household]);
	}
}pragma solidity ^0.4.4;

contract BalanceBook{
	struct Payment{
		int encrypted_change;
		bool active;
	}

	mapping (uint => address) coaches;
	mapping (uint => mapping (string => Payment)) private payments;
	mapping (uint => uint) public public_ns;
	mapping (uint => uint) public public_gs;
	address public owner;

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

	modifier onlyCoach(uint household) {
		if (msg.sender == coaches[household]) {
			_;
		}
	}

	function addHouseHold(uint household, uint n, uint g) {
		coaches[household] = msg.sender;
		public_ns[household] = n * n;
		public_gs[household] = g;
	}

	function removeHouseHold(uint household) onlyCoach(household) {
		delete coaches[household];
		delete public_ns[household];
		delete public_gs[household];
	}

	function addPayment(uint household, string company, int encrypted_change, bool active) onlyCoach(household) {
		Payment memory payment = Payment(encrypted_change, active);
		payments[household][company] = payment;
	}

	function togglePayment(uint household, string company) onlyCoach(household) {
		payments[household][company].active = !payments[household][company].active;
	}

	function getPayment(uint household, string company) returns (int, bool) {
	    Payment payment = payments[household][company];
	    return (payment.encrypted_change, payment.active);
	}

	function getPublicKeys(uint household) returns (uint, uint) {
		return (public_ns[household], public_gs[household]);
	}
}


Refactor redeem to use burn (DRY)

Refactor redeem to use burn (DRY)

pragma solidity ^0.4.11;

/// @title Abstract token contract - Functions to be implemented by token contracts.
contract Token {
    function transfer(address to, uint256 value) returns (bool success);
    function transferFrom(address from, address to, uint256 value) returns (bool success);
    function approve(address spender, uint256 value) returns (bool success);

    // This is not an abstract function, because solc won't recognize generated getter functions for public variables as functions.
    function totalSupply() constant returns (uint256 supply) {}
    function balanceOf(address owner) constant returns (uint256 balance);
    function allowance(address owner, address spender) constant returns (uint256 remaining);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/// @title Standard token contract - Standard token interface implementation.
contract StandardToken is Token {

    /*
     *  Data structures
     */
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;
    uint256 public totalSupply;

    /*
     *  Public functions
     */
    /// @dev Transfers sender's tokens to a given address. Returns success.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transfer(address _to, uint256 _value)
        public
        returns (bool)
    {
        require(balances[msg.sender] >= _value);

        balances[msg.sender] -= _value;
        balances[_to] += _value;
        Transfer(msg.sender, _to, _value);
        return true;
    }

    /// @dev Allows allowed third party to transfer tokens from one address to another. Returns success.
    /// @param _from Address from where tokens are withdrawn.
    /// @param _to Address to where tokens are sent.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transferFrom(address _from, address _to, uint256 _value)
        public
        returns (bool)
    {
        require(balances[_from] >= _value);
        require(allowed[_from][msg.sender] >= _value);

        balances[_to] += _value;
        balances[_from] -= _value;
        allowed[_from][msg.sender] -= _value;
        Transfer(_from, _to, _value);
        return true;
    }

    /// @dev Sets approved amount of tokens for spender. Returns success.
    /// @param _spender Address of allowed account.
    /// @param _value Number of approved tokens.
    /// @return Returns success of function call.
    function approve(address _spender, uint256 _value)
        public
        returns (bool)
    {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    /*
     * Read functions
     */
    /// @dev Returns number of allowed tokens for given address.
    /// @param _owner Address of token owner.
    /// @param _spender Address of token spender.
    /// @return Returns remaining allowance for spender.
    function allowance(address _owner, address _spender)
        constant
        public
        returns (uint256)
    {
        return allowed[_owner][_spender];
    }

    /// @dev Returns number of tokens owned by given address.
    /// @param _owner Address of token owner.
    /// @return Returns balance of owner.
    function balanceOf(address _owner)
        constant
        public
        returns (uint256)
    {
        return balances[_owner];
    }
}

/// @title Gnosis token contract
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract ReserveToken is StandardToken {

    /*
     *  Token meta data
     */
    string constant public name = "The Token";
    string constant public symbol = "TKN";
    uint8 constant public decimals = 18;
    uint constant multiplier = 10**uint(decimals);

    address auction_address;

    event Redeemed(address indexed receiver, uint num, uint unlocked, uint _totalSupply);
    event Burnt(address indexed receiver, uint num, uint _totalSupply);
    event ReceivedReserve(uint num);

    /*
     *  Public functions
     */
    /// @dev Contract constructor function sets dutch auction contract address and assigns all tokens to dutch auction.
    /// @param auction Address of dutch auction contract.
    /// @param owners Array of addresses receiving preassigned tokens.
    /// @param tokens Array of preassigned token amounts.
    function ReserveToken(address auction, address[] owners, uint[] tokens)
        public
    {
        // Auction address should not be null.
        require(auction != 0x0);

        auction_address = auction;
        totalSupply = 10000000 * multiplier;
        balances[auction] = 9000000 * multiplier;
        Transfer(0, auction, balances[auction]);
        uint assignedTokens = balances[auction];

        for (uint i=0; i<owners.length; i++) {
            // Address should not be null.
            require(owners[i] != 0x0);

            balances[owners[i]] += tokens[i];
            Transfer(0, owners[i], tokens[i]);
            assignedTokens += tokens[i];
        }
        assert(assignedTokens == totalSupply);
    }

    /// @dev Transfers auction's reserve; called from auction after it has ended.
    function receiveReserve()
        public
        payable
    {
        require(msg.sender == auction_address);
        ReceivedReserve(msg.value);
    }

    /// @dev Allows to destroy tokens and receive the corresponding amount of ether, implements the floor price
    /// @param num Number of tokens to redeem
    function redeem(uint num)
        public
    {
        require(num > 0);
        require(this.balance > 0);

        // Calculate amount of Wei to be transferred to sender before burning
        uint unlocked = this.balance * num / totalSupply;

        // Burn tokens before Wei transfer
        burn(num);

        // Transfer Wei to sender
        msg.sender.transfer(unlocked);
        Redeemed(msg.sender, num, unlocked, totalSupply);
    }

    /// @dev Allows to destroy tokens without receiving the corresponding amount of ether
    /// @param num Number of tokens to burn
    function burn(uint num)
        public
    {
        require(num > 0);
        require(balances[msg.sender] >= num);

        balances[msg.sender] -= num;
        totalSupply -= num;
        Burnt(msg.sender, num, totalSupply);
    }

}

pragma solidity ^0.4.11;

/// @title Abstract token contract - Functions to be implemented by token contracts.
contract Token {
    function transfer(address to, uint256 value) returns (bool success);
    function transferFrom(address from, address to, uint256 value) returns (bool success);
    function approve(address spender, uint256 value) returns (bool success);

    // This is not an abstract function, because solc won't recognize generated getter functions for public variables as functions.
    function totalSupply() constant returns (uint256 supply) {}
    function balanceOf(address owner) constant returns (uint256 balance);
    function allowance(address owner, address spender) constant returns (uint256 remaining);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/// @title Standard token contract - Standard token interface implementation.
contract StandardToken is Token {

    /*
     *  Data structures
     */
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;
    uint256 public totalSupply;

    /*
     *  Public functions
     */
    /// @dev Transfers sender's tokens to a given address. Returns success.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transfer(address _to, uint256 _value)
        public
        returns (bool)
    {
        require(balances[msg.sender] >= _value);

        balances[msg.sender] -= _value;
        balances[_to] += _value;
        Transfer(msg.sender, _to, _value);
        return true;
    }

    /// @dev Allows allowed third party to transfer tokens from one address to another. Returns success.
    /// @param _from Address from where tokens are withdrawn.
    /// @param _to Address to where tokens are sent.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transferFrom(address _from, address _to, uint256 _value)
        public
        returns (bool)
    {
        require(balances[_from] >= _value);
        require(allowed[_from][msg.sender] >= _value);

        balances[_to] += _value;
        balances[_from] -= _value;
        allowed[_from][msg.sender] -= _value;
        Transfer(_from, _to, _value);
        return true;
    }

    /// @dev Sets approved amount of tokens for spender. Returns success.
    /// @param _spender Address of allowed account.
    /// @param _value Number of approved tokens.
    /// @return Returns success of function call.
    function approve(address _spender, uint256 _value)
        public
        returns (bool)
    {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    /*
     * Read functions
     */
    /// @dev Returns number of allowed tokens for given address.
    /// @param _owner Address of token owner.
    /// @param _spender Address of token spender.
    /// @return Returns remaining allowance for spender.
    function allowance(address _owner, address _spender)
        constant
        public
        returns (uint256)
    {
        return allowed[_owner][_spender];
    }

    /// @dev Returns number of tokens owned by given address.
    /// @param _owner Address of token owner.
    /// @return Returns balance of owner.
    function balanceOf(address _owner)
        constant
        public
        returns (uint256)
    {
        return balances[_owner];
    }
}

/// @title Gnosis token contract
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract ReserveToken is StandardToken {

    /*
     *  Token meta data
     */
    string constant public name = "The Token";
    string constant public symbol = "TKN";
    uint8 constant public decimals = 18;
    uint constant multiplier = 10**uint(decimals);

    address auction_address;

    event Redeemed(address indexed receiver, uint num, uint unlocked, uint _totalSupply);
    event Burnt(address indexed receiver, uint num, uint _totalSupply);
    event ReceivedReserve(uint num);

    /*
     *  Public functions
     */
    /// @dev Contract constructor function sets dutch auction contract address and assigns all tokens to dutch auction.
    /// @param auction Address of dutch auction contract.
    /// @param owners Array of addresses receiving preassigned tokens.
    /// @param tokens Array of preassigned token amounts.
    function ReserveToken(address auction, address[] owners, uint[] tokens)
        public
    {
        // Auction address should not be null.
        require(auction != 0x0);

        auction_address = auction;
        totalSupply = 10000000 * multiplier;
        balances[auction] = 9000000 * multiplier;
        Transfer(0, auction, balances[auction]);
        uint assignedTokens = balances[auction];

        for (uint i=0; i<owners.length; i++) {
            // Address should not be null.
            require(owners[i] != 0x0);

            balances[owners[i]] += tokens[i];
            Transfer(0, owners[i], tokens[i]);
            assignedTokens += tokens[i];
        }
        assert(assignedTokens == totalSupply);
    }

    /// @dev Transfers auction's reserve; called from auction after it has ended.
    function receiveReserve()
        public
        payable
    {
        require(msg.sender == auction_address);
        ReceivedReserve(msg.value);
    }

    /// @dev Allows to destroy tokens and receive the corresponding amount of ether, implements the floor price
    /// @param num Number of tokens to redeem
    function redeem(uint num)
        public
    {
        require(num > 0);
        require(balances[msg.sender] >= num);
        require(this.balance > 0);

        balances[msg.sender] -= num;
        uint unlocked = this.balance * num / totalSupply;
        totalSupply -= num;
        msg.sender.transfer(unlocked);
        Redeemed(msg.sender, num, unlocked, totalSupply);
    }

    /// @dev Allows to destroy tokens without receiving the corresponding amount of ether
    /// @param num Number of tokens to burn
    function burn(uint num)
        public
    {
        require(num > 0);
        require(balances[msg.sender] >= num);

        balances[msg.sender] -= num;
        totalSupply -= num;
        Burnt(msg.sender, num, totalSupply);
    }

}