contract PledgePoolBase is RBACOperator {
  using SafeMath for uint256;
  using AddressUtils for address;

  // Record pledge details.
  mapping(uint256 => Escrow) internal escrows;

  /**
   * @dev Information structure of pledge.
   */
  struct Escrow {
    uint256 pledgeSum;
    address payerAddress;
    string tokenName;
  }

  // -----------------------------------------
  // TokenPool external interface
  // -----------------------------------------

  /**
   * @dev addRecord, interface to add record.
   * @param _payerAddress Address performing the pleadge.
   * @param _pledgeSum the value to pleadge.
   * @param _pledgeId pledge contract index number.
   * @param _tokenName pledge token name.
   */
  function addRecord(address _payerAddress, uint256 _pledgeSum, uint256 _pledgeId, string _tokenName) public hasOperationPermission returns(bool) {
    _preValidateAddRecord(_payerAddress, _pledgeSum, _pledgeId, _tokenName);
    _processAddRecord(_payerAddress, _pledgeSum, _pledgeId, _tokenName);
    return true;
  }


   /**
    * @dev withdrawToken, withdraw pledge token.
    * @param _pledgeId pledge contract index number.
    * @param _maker borrower address.
    * @param _num withdraw token sum.
    */
  function withdrawToken(uint256 _pledgeId, address _maker, uint256 _num) public hasOperationPermission returns(bool) {
    _preValidateWithdraw(_maker, _num, _pledgeId);
    _processWithdraw(_maker, _num, _pledgeId);
    return true;
  }


  /**
   * @dev refundTokens, interface to refund
   * @param _pledgeId pledge contract index number.
   * @param _targetAddress transfer target address.
   * @param _returnSum return token sum.
   */
  function refundTokens(uint256 _pledgeId, uint256 _returnSum, address _targetAddress) public hasOperationPermission returns(bool) {
    _preValidateRefund(_returnSum, _targetAddress, _pledgeId);
    _processRefund(_returnSum, _targetAddress, _pledgeId);
    return true;
  }

  /**
   * @dev getLedger, Query the pledge details of the pledge number in the pool.
   * @param _pledgeId pledge contract index number.
   */
  function getLedger(uint256 _pledgeId) public view returns(uint256 num, address payerAddress, string tokenName) {
    require(_pledgeId > 0);
    num = escrows[_pledgeId].pledgeSum;
    payerAddress = escrows[_pledgeId].payerAddress;
    tokenName = escrows[_pledgeId].tokenName;
  }



  // -----------------------------------------
  // TokenPool internal interface (extensible)
  // -----------------------------------------



  /**
   * @dev _preValidateAddRecord, Validation of an incoming AddRecord. Use require statemens to revert state when conditions are not met.
   * @param _payerAddress Address performing the pleadge.
   * @param _pledgeSum the value to pleadge.
   * @param _pledgeId pledge contract index number.
   * @param _tokenName pledge token name.
   */
  function _preValidateAddRecord(address _payerAddress, uint256 _pledgeSum, uint256 _pledgeId, string _tokenName) view internal {
    require(_pledgeSum > 0 && _pledgeId > 0
      && _payerAddress != address(0)
      && bytes(_tokenName).length > 0
      && address(msg.sender).isContract()
      && PledgeContract(msg.sender).getPledgeId()==_pledgeId
    );
  }

  /**
   * @dev _processAddRecord, Executed when a AddRecord has been validated and is ready to be executed. Not necessarily emits/sends tokens.
   * @param _payerAddress Address performing the pleadge.
   * @param _pledgeSum the value to pleadge.
   * @param _pledgeId pledge contract index number.
   * @param _tokenName pledge token name.
   */
  function _processAddRecord(address _payerAddress, uint256 _pledgeSum, uint256 _pledgeId, string _tokenName) internal {
    Escrow memory escrow = Escrow(_pledgeSum, _payerAddress, _tokenName);
    escrows[_pledgeId] = escrow;
  }



  /**
   * @dev _preValidateRefund, Validation of an incoming refund. Use require statemens to revert state when conditions are not met.
   * @param _pledgeId pledge contract index number.
   * @param _targetAddress transfer target address.
   * @param _returnSum return token sum.
   */
  function _preValidateRefund(uint256 _returnSum, address _targetAddress, uint256 _pledgeId) view internal {
    require(_returnSum > 0 && _pledgeId > 0
      && _targetAddress != address(0)
      && address(msg.sender).isContract()
      && _returnSum <= escrows[_pledgeId].pledgeSum
      && PledgeContract(msg.sender).getPledgeId()==_pledgeId
    );
  }


  /**
   * @dev _processRefund, Executed when a Refund has been validated and is ready to be executed. Not necessarily emits/sends tokens.
   * @param _pledgeId pledge contract index number.
   * @param _targetAddress transfer target address.
   * @param _returnSum return token sum.
   */
  function _processRefund(uint256 _returnSum, address _targetAddress, uint256 _pledgeId) internal {
    escrows[_pledgeId].pledgeSum = escrows[_pledgeId].pledgeSum.sub(_returnSum);
  }



  /**
   * @dev _preValidateWithdraw, Withdraw initiated parameter validation.
   * @param _pledgeId pledge contract index number.
   * @param _maker borrower address.
   * @param _num withdraw token sum.
   */
  function _preValidateWithdraw(address _maker, uint256 _num, uint256 _pledgeId) view internal {
    require(_num > 0 && _pledgeId > 0
       && _maker != address(0)
       && address(msg.sender).isContract()
       && _num <= escrows[_pledgeId].pledgeSum
       && PledgeContract(msg.sender).getPledgeId()==_pledgeId
    );
  }


  /**
   * @dev _processWithdraw, Withdraw data update.
   * @param _pledgeId pledge contract index number.
   * @param _maker borrower address.
   * @param _num withdraw token sum.
   */
  function _processWithdraw(address _maker, uint256 _num, uint256 _pledgeId) internal {
    escrows[_pledgeId].pledgeSum = escrows[_pledgeId].pledgeSum.sub(_num);
  }

}
/**
 * @title pledge pool base
 * @dev a base tokenPool, any tokenPool for a specific token should inherit from this tokenPool.
 */
function _preValidateAddRecord(address _payerAddress, uint256 _pledgeSum, uint256 _pledgeId, string _tokenName) view internal {
  require(_pledgeSum > 0 && _pledgeId > 0
    && _payerAddress != address(0)
    && bytes(_tokenName).length > 0
    && address(msg.sender).isContract()
    && PledgeContract(msg.sender).getPledgeId()==_pledgeId
  );
}

/**
 * @dev _preValidateAddRecord, Validation of an incoming AddRecord. Use require statemens to revert state when conditions are not met.
 * @param _payerAddress Address performing the pleadge.
 * @param _pledgeSum the value to pleadge.
 * @param _pledgeId pledge contract index number.
 * @param _tokenName pledge token name.
 */