ETH Price: $3,186.50 (+5.04%)

Contract

0x9Eda313cF60F1d004E493fCc123d64c21ef7E6A7
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer138652312021-12-24 2:45:231052 days ago1640313923IN
Open Grants: zktube
0.001 ETH0.0047746988.4269017
Transfer134916622021-10-26 7:32:171111 days ago1635233537IN
Open Grants: zktube
0.05 ETH0.0048374589.48645313
Transfer134854212021-10-25 8:06:011112 days ago1635149161IN
Open Grants: zktube
0.001 ETH0.0036084166.82737877
Transfer133850272021-10-09 14:15:471127 days ago1633788947IN
Open Grants: zktube
0.001 ETH0.004388781.27825836
Transfer132473172021-09-18 3:35:171149 days ago1631936117IN
Open Grants: zktube
0.01 ETH0.001926335.65455205
Transfer132370172021-09-16 13:26:261150 days ago1631798786IN
Open Grants: zktube
0.0002 ETH0.0034919664.59671985
Transfer132308552021-09-15 14:33:161151 days ago1631716396IN
Open Grants: zktube
0.001 ETH0.0045667384.57549464
Transfer132303062021-09-15 12:29:571152 days ago1631708997IN
Open Grants: zktube
0.2 ETH0.0021936240.60232639
Transfer132302102021-09-15 12:10:521152 days ago1631707852IN
Open Grants: zktube
0.001 ETH0.002715950.29822708
Transfer132299422021-09-15 11:07:491152 days ago1631704069IN
Open Grants: zktube
0.01 ETH0.0027196550.3387458
Transfer132098852021-09-12 8:31:571155 days ago1631435517IN
Open Grants: zktube
0.01 ETH0.003619867.00000145
Transfer130743452021-08-22 9:46:031176 days ago1629625563IN
Open Grants: zktube
0.005 ETH0.0012869423.82661778
Transfer128694592021-07-21 11:14:111208 days ago1626866051IN
Open Grants: zktube
0.001 ETH0.0005939511
Transfer127651432021-07-05 3:46:231224 days ago1625456783IN
Open Grants: zktube
0.001 ETH0.0005399610
Transfer127472212021-07-02 8:55:531227 days ago1625216153IN
Open Grants: zktube
0.002 ETH0.0005941411
Transfer127472062021-07-02 8:52:061227 days ago1625215926IN
Open Grants: zktube
0.002 ETH0.0005401310
Transfer127471842021-07-02 8:45:021227 days ago1625215502IN
Open Grants: zktube
0.002 ETH0.0005401310
Transfer127471742021-07-02 8:42:351227 days ago1625215355IN
Open Grants: zktube
0.0024 ETH0.0005402710
Transfer127471612021-07-02 8:39:241227 days ago1625215164IN
Open Grants: zktube
0.0025 ETH0.0005402710
Transfer127471392021-07-02 8:34:301227 days ago1625214870IN
Open Grants: zktube
0.0025 ETH0.0005402710
Transfer127471122021-07-02 8:29:181227 days ago1625214558IN
Open Grants: zktube
0.01 ETH0.0006483212
Transfer127301082021-06-29 16:51:431229 days ago1624985503IN
Open Grants: zktube
0.0234 ETH0.0014051426
Transfer127210992021-06-28 7:06:421231 days ago1624864002IN
Open Grants: zktube
0.06 ETH0.0005946311
Transfer126938902021-06-24 1:16:521235 days ago1624497412IN
Open Grants: zktube
0.002 ETH0.0005401310
Transfer126859602021-06-22 19:40:081236 days ago1624390808IN
Open Grants: zktube
0.001 ETH0.0008639316
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
138652312021-12-24 2:45:231052 days ago1640313923
Open Grants: zktube
0.001 ETH
137949422021-12-13 5:29:451063 days ago1639373385
Open Grants: zktube
0.00685251 ETH
137949422021-12-13 5:29:451063 days ago1639373385
Open Grants: zktube
0.00685251 ETH
136005152021-11-12 9:25:271094 days ago1636709127
Open Grants: zktube
0.04287854 ETH
136005152021-11-12 9:25:271094 days ago1636709127
Open Grants: zktube
0.04287854 ETH
134916622021-10-26 7:32:171111 days ago1635233537
Open Grants: zktube
0.05 ETH
134854212021-10-25 8:06:011112 days ago1635149161
Open Grants: zktube
0.001 ETH
133850272021-10-09 14:15:471127 days ago1633788947
Open Grants: zktube
0.001 ETH
132473172021-09-18 3:35:171149 days ago1631936117
Open Grants: zktube
0.01 ETH
132370172021-09-16 13:26:261150 days ago1631798786
Open Grants: zktube
0.0002 ETH
132308552021-09-15 14:33:161151 days ago1631716396
Open Grants: zktube
0.001 ETH
132303062021-09-15 12:29:571152 days ago1631708997
Open Grants: zktube
0.2 ETH
132302102021-09-15 12:10:521152 days ago1631707852
Open Grants: zktube
0.001 ETH
132299422021-09-15 11:07:491152 days ago1631704069
Open Grants: zktube
0.01 ETH
132098852021-09-12 8:31:571155 days ago1631435517
Open Grants: zktube
0.01 ETH
130743452021-08-22 9:46:031176 days ago1629625563
Open Grants: zktube
0.005 ETH
128694592021-07-21 11:14:111208 days ago1626866051
Open Grants: zktube
0.001 ETH
127651432021-07-05 3:46:231224 days ago1625456783
Open Grants: zktube
0.001 ETH
127472212021-07-02 8:55:531227 days ago1625216153
Open Grants: zktube
0.002 ETH
127472062021-07-02 8:52:061227 days ago1625215926
Open Grants: zktube
0.002 ETH
127471842021-07-02 8:45:021227 days ago1625215502
Open Grants: zktube
0.002 ETH
127471742021-07-02 8:42:351227 days ago1625215355
Open Grants: zktube
0.0024 ETH
127471612021-07-02 8:39:241227 days ago1625215164
Open Grants: zktube
0.0025 ETH
127471392021-07-02 8:34:301227 days ago1625214870
Open Grants: zktube
0.0025 ETH
127471122021-07-02 8:29:181227 days ago1625214558
Open Grants: zktube
0.01 ETH
View All Internal Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x53E7daA8...BaDa17064
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
UnmanagedGrant

Compiler Version
v0.7.0+commit.9e61f92b

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-12-15
*/

/**
 *Submitted for verification at Etherscan.io on 2020-12-03
*/

// File: @openzeppelin/contracts/utils/ReentrancyGuard.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor () {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: contracts/shared/libraries/abdk-libraries/ABDKMathQuad.sol

/*
 * ABDK Math Quad Smart Contract Library.  Copyright © 2019 by ABDK Consulting.
 * Author: Mikhail Vladimirov <[email protected]>
 */
pragma solidity ^0.7.0;

/**
 * Smart contract library of mathematical functions operating with IEEE 754
 * quadruple-precision binary floating-point numbers (quadruple precision
 * numbers).  As long as quadruple precision numbers are 16-bytes long, they are
 * represented by bytes16 type.
 */
library ABDKMathQuad {
  /*
   * 0.
   */
  bytes16 private constant POSITIVE_ZERO = 0x00000000000000000000000000000000;

  /*
   * -0.
   */
  bytes16 private constant NEGATIVE_ZERO = 0x80000000000000000000000000000000;

  /*
   * +Infinity.
   */
  bytes16 private constant POSITIVE_INFINITY = 0x7FFF0000000000000000000000000000;

  /*
   * -Infinity.
   */
  bytes16 private constant NEGATIVE_INFINITY = 0xFFFF0000000000000000000000000000;

  /*
   * Canonical NaN value.
   */
  bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;

  /**
   * Convert signed 256-bit integer number into quadruple precision number.
   *
   * @param x signed 256-bit integer number
   * @return quadruple precision number
   */
  function fromInt (int256 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      // We rely on overflow behavior here
      uint256 result = uint256 (x > 0 ? x : -x);

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112;
      if (x < 0) result |= 0x80000000000000000000000000000000;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into signed 256-bit integer number
   * rounding towards zero.  Revert on overflow.
   *
   * @param x quadruple precision number
   * @return signed 256-bit integer number
   */
  function toInt (bytes16 x) internal pure returns (int256) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    require (exponent <= 16638); // Overflow
    if (exponent < 16383) return 0; // Underflow

    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16495) result >>= 16495 - exponent;
    else if (exponent > 16495) result <<= exponent - 16495;

    if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative
      require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000);
      return -int256 (result); // We rely on overflow behavior here
    } else {
      require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int256 (result);
    }
  }

  /**
   * Convert unsigned 256-bit integer number into quadruple precision number.
   *
   * @param x unsigned 256-bit integer number
   * @return quadruple precision number
   */
  function fromUInt (uint256 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      uint256 result = x;

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into unsigned 256-bit integer number
   * rounding towards zero.  Revert on underflow.  Note, that negative floating
   * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer
   * without error, because they are rounded to zero.
   *
   * @param x quadruple precision number
   * @return unsigned 256-bit integer number
   */
  function toUInt (bytes16 x) internal pure returns (uint256) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    if (exponent < 16383) return 0; // Underflow

    require (uint128 (x) < 0x80000000000000000000000000000000); // Negative

    require (exponent <= 16638); // Overflow
    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16495) result >>= 16495 - exponent;
    else if (exponent > 16495) result <<= exponent - 16495;

    return result;
  }

  /**
   * Convert signed 128.128 bit fixed point number into quadruple precision
   * number.
   *
   * @param x signed 128.128 bit fixed point number
   * @return quadruple precision number
   */
  function from128x128 (int256 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      // We rely on overflow behavior here
      uint256 result = uint256 (x > 0 ? x : -x);

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16255 + msb << 112;
      if (x < 0) result |= 0x80000000000000000000000000000000;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into signed 128.128 bit fixed point
   * number.  Revert on overflow.
   *
   * @param x quadruple precision number
   * @return signed 128.128 bit fixed point number
   */
  function to128x128 (bytes16 x) internal pure returns (int256) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    require (exponent <= 16510); // Overflow
    if (exponent < 16255) return 0; // Underflow

    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16367) result >>= 16367 - exponent;
    else if (exponent > 16367) result <<= exponent - 16367;

    if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative
      require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000);
      return -int256 (result); // We rely on overflow behavior here
    } else {
      require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int256 (result);
    }
  }

  /**
   * Convert signed 64.64 bit fixed point number into quadruple precision
   * number.
   *
   * @param x signed 64.64 bit fixed point number
   * @return quadruple precision number
   */
  function from64x64 (int128 x) internal pure returns (bytes16) {
    if (x == 0) return bytes16 (0);
    else {
      // We rely on overflow behavior here
      uint256 result = uint128 (x > 0 ? x : -x);

      uint256 msb = msb (result);
      if (msb < 112) result <<= 112 - msb;
      else if (msb > 112) result >>= msb - 112;

      result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16319 + msb << 112;
      if (x < 0) result |= 0x80000000000000000000000000000000;

      return bytes16 (uint128 (result));
    }
  }

  /**
   * Convert quadruple precision number into signed 64.64 bit fixed point
   * number.  Revert on overflow.
   *
   * @param x quadruple precision number
   * @return signed 64.64 bit fixed point number
   */
  function to64x64 (bytes16 x) internal pure returns (int128) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    require (exponent <= 16446); // Overflow
    if (exponent < 16319) return 0; // Underflow

    uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
      0x10000000000000000000000000000;

    if (exponent < 16431) result >>= 16431 - exponent;
    else if (exponent > 16431) result <<= exponent - 16431;

    if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative
      require (result <= 0x80000000000000000000000000000000);
      return -int128 (result); // We rely on overflow behavior here
    } else {
      require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (result);
    }
  }

  /**
   * Convert octuple precision number into quadruple precision number.
   *
   * @param x octuple precision number
   * @return quadruple precision number
   */
  function fromOctuple (bytes32 x) internal pure returns (bytes16) {
    bool negative = x & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0;

    uint256 exponent = uint256 (x) >> 236 & 0x7FFFF;
    uint256 significand = uint256 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (exponent == 0x7FFFF) {
      if (significand > 0) return NaN;
      else return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
    }

    if (exponent > 278526)
      return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
    else if (exponent < 245649)
      return negative ? NEGATIVE_ZERO : POSITIVE_ZERO;
    else if (exponent < 245761) {
      significand = (significand | 0x100000000000000000000000000000000000000000000000000000000000) >> 245885 - exponent;
      exponent = 0;
    } else {
      significand >>= 124;
      exponent -= 245760;
    }

    uint128 result = uint128 (significand | exponent << 112);
    if (negative) result |= 0x80000000000000000000000000000000;

    return bytes16 (result);
  }

  /**
   * Convert quadruple precision number into octuple precision number.
   *
   * @param x quadruple precision number
   * @return octuple precision number
   */
  function toOctuple (bytes16 x) internal pure returns (bytes32) {
    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;

    uint256 result = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (exponent == 0x7FFF) exponent = 0x7FFFF; // Infinity or NaN
    else if (exponent == 0) {
      if (result > 0) {
        uint256 msb = msb (result);
        result = result << 236 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        exponent = 245649 + msb;
      }
    } else {
      result <<= 124;
      exponent += 245760;
    }

    result |= exponent << 236;
    if (uint128 (x) >= 0x80000000000000000000000000000000)
      result |= 0x8000000000000000000000000000000000000000000000000000000000000000;

    return bytes32 (result);
  }

  /**
   * Convert double precision number into quadruple precision number.
   *
   * @param x double precision number
   * @return quadruple precision number
   */
  function fromDouble (bytes8 x) internal pure returns (bytes16) {
    uint256 exponent = uint64 (x) >> 52 & 0x7FF;

    uint256 result = uint64 (x) & 0xFFFFFFFFFFFFF;

    if (exponent == 0x7FF) exponent = 0x7FFF; // Infinity or NaN
    else if (exponent == 0) {
      if (result > 0) {
        uint256 msb = msb (result);
        result = result << 112 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        exponent = 15309 + msb;
      }
    } else {
      result <<= 60;
      exponent += 15360;
    }

    result |= exponent << 112;
    if (x & 0x8000000000000000 > 0)
      result |= 0x80000000000000000000000000000000;

    return bytes16 (uint128 (result));
  }

  /**
   * Convert quadruple precision number into double precision number.
   *
   * @param x quadruple precision number
   * @return double precision number
   */
  function toDouble (bytes16 x) internal pure returns (bytes8) {
    bool negative = uint128 (x) >= 0x80000000000000000000000000000000;

    uint256 exponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 significand = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (exponent == 0x7FFF) {
      if (significand > 0) return 0x7FF8000000000000; // NaN
      else return negative ?
          bytes8 (0xFFF0000000000000) : // -Infinity
          bytes8 (0x7FF0000000000000); // Infinity
    }

    if (exponent > 17406)
      return negative ?
          bytes8 (0xFFF0000000000000) : // -Infinity
          bytes8 (0x7FF0000000000000); // Infinity
    else if (exponent < 15309)
      return negative ?
          bytes8 (0x8000000000000000) : // -0
          bytes8 (0x0000000000000000); // 0
    else if (exponent < 15361) {
      significand = (significand | 0x10000000000000000000000000000) >> 15421 - exponent;
      exponent = 0;
    } else {
      significand >>= 60;
      exponent -= 15360;
    }

    uint64 result = uint64 (significand | exponent << 52);
    if (negative) result |= 0x8000000000000000;

    return bytes8 (result);
  }

  /**
   * Test whether given quadruple precision number is NaN.
   *
   * @param x quadruple precision number
   * @return true if x is NaN, false otherwise
   */
  function isNaN (bytes16 x) internal pure returns (bool) {
    return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >
      0x7FFF0000000000000000000000000000;
  }

  /**
   * Test whether given quadruple precision number is positive or negative
   * infinity.
   *
   * @param x quadruple precision number
   * @return true if x is positive or negative infinity, false otherwise
   */
  function isInfinity (bytes16 x) internal pure returns (bool) {
    return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==
      0x7FFF0000000000000000000000000000;
  }

  /**
   * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x
   * is positive.  Note that sign (-0) is zero.  Revert if x is NaN. 
   *
   * @param x quadruple precision number
   * @return sign of x
   */
  function sign (bytes16 x) internal pure returns (int8) {
    uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN

    if (absoluteX == 0) return 0;
    else if (uint128 (x) >= 0x80000000000000000000000000000000) return -1;
    else return 1;
  }

  /**
   * Calculate sign (x - y).  Revert if either argument is NaN, or both
   * arguments are infinities of the same sign. 
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return sign (x - y)
   */
  function cmp (bytes16 x, bytes16 y) internal pure returns (int8) {
    uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN

    uint128 absoluteY = uint128 (y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    require (absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN

    // Not infinities of the same sign
    require (x != y || absoluteX < 0x7FFF0000000000000000000000000000);

    if (x == y) return 0;
    else {
      bool negativeX = uint128 (x) >= 0x80000000000000000000000000000000;
      bool negativeY = uint128 (y) >= 0x80000000000000000000000000000000;

      if (negativeX) {
        if (negativeY) return absoluteX > absoluteY ? -1 : int8 (1);
        else return -1; 
      } else {
        if (negativeY) return 1;
        else return absoluteX > absoluteY ? int8 (1) : -1;
      }
    }
  }

  /**
   * Test whether x equals y.  NaN, infinity, and -infinity are not equal to
   * anything. 
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return true if x equals to y, false otherwise
   */
  function eq (bytes16 x, bytes16 y) internal pure returns (bool) {
    if (x == y) {
      return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <
        0x7FFF0000000000000000000000000000;
    } else return false;
  }

  /**
   * Calculate x + y.  Special values behave in the following way:
   *
   * NaN + x = NaN for any x.
   * Infinity + x = Infinity for any finite x.
   * -Infinity + x = -Infinity for any finite x.
   * Infinity + Infinity = Infinity.
   * -Infinity + -Infinity = -Infinity.
   * Infinity + -Infinity = -Infinity + Infinity = NaN.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function add (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;

    if (xExponent == 0x7FFF) {
      if (yExponent == 0x7FFF) { 
        if (x == y) return x;
        else return NaN;
      } else return x; 
    } else if (yExponent == 0x7FFF) return y;
    else {
      bool xSign = uint128 (x) >= 0x80000000000000000000000000000000;
      uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xExponent == 0) xExponent = 1;
      else xSignifier |= 0x10000000000000000000000000000;

      bool ySign = uint128 (y) >= 0x80000000000000000000000000000000;
      uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (yExponent == 0) yExponent = 1;
      else ySignifier |= 0x10000000000000000000000000000;

      if (xSignifier == 0) return y == NEGATIVE_ZERO ? POSITIVE_ZERO : y;
      else if (ySignifier == 0) return x == NEGATIVE_ZERO ? POSITIVE_ZERO : x;
      else {
        int256 delta = int256 (xExponent) - int256 (yExponent);
  
        if (xSign == ySign) {
          if (delta > 112) return x;
          else if (delta > 0) ySignifier >>= uint256 (delta);
          else if (delta < -112) return y;
          else if (delta < 0) {
            xSignifier >>= uint256 (-delta);
            xExponent = yExponent;
          }
  
          xSignifier += ySignifier;
  
          if (xSignifier >= 0x20000000000000000000000000000) {
            xSignifier >>= 1;
            xExponent += 1;
          }
  
          if (xExponent == 0x7FFF)
            return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
          else {
            if (xSignifier < 0x10000000000000000000000000000) xExponent = 0;
            else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
  
            return bytes16 (uint128 (
                (xSign ? 0x80000000000000000000000000000000 : 0) |
                (xExponent << 112) |
                xSignifier)); 
          }
        } else {
          if (delta > 0) {
            xSignifier <<= 1;
            xExponent -= 1;
          } else if (delta < 0) {
            ySignifier <<= 1;
            xExponent = yExponent - 1;
          }

          if (delta > 112) ySignifier = 1;
          else if (delta > 1) ySignifier = (ySignifier - 1 >> uint256 (delta - 1)) + 1;
          else if (delta < -112) xSignifier = 1;
          else if (delta < -1) xSignifier = (xSignifier - 1 >> uint256 (-delta - 1)) + 1;

          if (xSignifier >= ySignifier) xSignifier -= ySignifier;
          else {
            xSignifier = ySignifier - xSignifier;
            xSign = ySign;
          }

          if (xSignifier == 0)
            return POSITIVE_ZERO;

          uint256 msb = msb (xSignifier);

          if (msb == 113) {
            xSignifier = xSignifier >> 1 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            xExponent += 1;
          } else if (msb < 112) {
            uint256 shift = 112 - msb;
            if (xExponent > shift) {
              xSignifier = xSignifier << shift & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
              xExponent -= shift;
            } else {
              xSignifier <<= xExponent - 1;
              xExponent = 0;
            }
          } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

          if (xExponent == 0x7FFF)
            return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
          else return bytes16 (uint128 (
              (xSign ? 0x80000000000000000000000000000000 : 0) |
              (xExponent << 112) |
              xSignifier));
        }
      }
    }
  }

  /**
   * Calculate x - y.  Special values behave in the following way:
   *
   * NaN - x = NaN for any x.
   * Infinity - x = Infinity for any finite x.
   * -Infinity - x = -Infinity for any finite x.
   * Infinity - -Infinity = Infinity.
   * -Infinity - Infinity = -Infinity.
   * Infinity - Infinity = -Infinity - -Infinity = NaN.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function sub (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    return add (x, y ^ 0x80000000000000000000000000000000);
  }

  /**
   * Calculate x * y.  Special values behave in the following way:
   *
   * NaN * x = NaN for any x.
   * Infinity * x = Infinity for any finite positive x.
   * Infinity * x = -Infinity for any finite negative x.
   * -Infinity * x = -Infinity for any finite positive x.
   * -Infinity * x = Infinity for any finite negative x.
   * Infinity * 0 = NaN.
   * -Infinity * 0 = NaN.
   * Infinity * Infinity = Infinity.
   * Infinity * -Infinity = -Infinity.
   * -Infinity * Infinity = -Infinity.
   * -Infinity * -Infinity = Infinity.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function mul (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;

    if (xExponent == 0x7FFF) {
      if (yExponent == 0x7FFF) {
        if (x == y) return x ^ y & 0x80000000000000000000000000000000;
        else if (x ^ y == 0x80000000000000000000000000000000) return x | y;
        else return NaN;
      } else {
        if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
        else return x ^ y & 0x80000000000000000000000000000000;
      }
    } else if (yExponent == 0x7FFF) {
        if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
        else return y ^ x & 0x80000000000000000000000000000000;
    } else {
      uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xExponent == 0) xExponent = 1;
      else xSignifier |= 0x10000000000000000000000000000;

      uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (yExponent == 0) yExponent = 1;
      else ySignifier |= 0x10000000000000000000000000000;

      xSignifier *= ySignifier;
      if (xSignifier == 0)
        return (x ^ y) & 0x80000000000000000000000000000000 > 0 ?
            NEGATIVE_ZERO : POSITIVE_ZERO;

      xExponent += yExponent;

      uint256 msb =
        xSignifier >= 0x200000000000000000000000000000000000000000000000000000000 ? 225 :
        xSignifier >= 0x100000000000000000000000000000000000000000000000000000000 ? 224 :
        msb (xSignifier);

      if (xExponent + msb < 16496) { // Underflow
        xExponent = 0;
        xSignifier = 0;
      } else if (xExponent + msb < 16608) { // Subnormal
        if (xExponent < 16496)
          xSignifier >>= 16496 - xExponent;
        else if (xExponent > 16496)
          xSignifier <<= xExponent - 16496;
        xExponent = 0;
      } else if (xExponent + msb > 49373) {
        xExponent = 0x7FFF;
        xSignifier = 0;
      } else {
        if (msb > 112)
          xSignifier >>= msb - 112;
        else if (msb < 112)
          xSignifier <<= 112 - msb;

        xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

        xExponent = xExponent + msb - 16607;
      }

      return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) |
          xExponent << 112 | xSignifier));
    }
  }

  /**
   * Calculate x / y.  Special values behave in the following way:
   *
   * NaN / x = NaN for any x.
   * x / NaN = NaN for any x.
   * Infinity / x = Infinity for any finite non-negative x.
   * Infinity / x = -Infinity for any finite negative x including -0.
   * -Infinity / x = -Infinity for any finite non-negative x.
   * -Infinity / x = Infinity for any finite negative x including -0.
   * x / Infinity = 0 for any finite non-negative x.
   * x / -Infinity = -0 for any finite non-negative x.
   * x / Infinity = -0 for any finite non-negative x including -0.
   * x / -Infinity = 0 for any finite non-negative x including -0.
   * 
   * Infinity / Infinity = NaN.
   * Infinity / -Infinity = -NaN.
   * -Infinity / Infinity = -NaN.
   * -Infinity / -Infinity = NaN.
   *
   * Division by zero behaves in the following way:
   *
   * x / 0 = Infinity for any finite positive x.
   * x / -0 = -Infinity for any finite positive x.
   * x / 0 = -Infinity for any finite negative x.
   * x / -0 = Infinity for any finite negative x.
   * 0 / 0 = NaN.
   * 0 / -0 = NaN.
   * -0 / 0 = NaN.
   * -0 / -0 = NaN.
   *
   * @param x quadruple precision number
   * @param y quadruple precision number
   * @return quadruple precision number
   */
  function div (bytes16 x, bytes16 y) internal pure returns (bytes16) {
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 yExponent = uint128 (y) >> 112 & 0x7FFF;

    if (xExponent == 0x7FFF) {
      if (yExponent == 0x7FFF) return NaN;
      else return x ^ y & 0x80000000000000000000000000000000;
    } else if (yExponent == 0x7FFF) {
      if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;
      else return POSITIVE_ZERO | (x ^ y) & 0x80000000000000000000000000000000;
    } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {
      if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;
      else return POSITIVE_INFINITY | (x ^ y) & 0x80000000000000000000000000000000;
    } else {
      uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (yExponent == 0) yExponent = 1;
      else ySignifier |= 0x10000000000000000000000000000;

      uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xExponent == 0) {
        if (xSignifier != 0) {
          uint shift = 226 - msb (xSignifier);

          xSignifier <<= shift;

          xExponent = 1;
          yExponent += shift - 114;
        }
      }
      else {
        xSignifier = (xSignifier | 0x10000000000000000000000000000) << 114;
      }

      xSignifier = xSignifier / ySignifier;
      if (xSignifier == 0)
        return (x ^ y) & 0x80000000000000000000000000000000 > 0 ?
            NEGATIVE_ZERO : POSITIVE_ZERO;

      assert (xSignifier >= 0x1000000000000000000000000000);

      uint256 msb =
        xSignifier >= 0x80000000000000000000000000000 ? msb (xSignifier) :
        xSignifier >= 0x40000000000000000000000000000 ? 114 :
        xSignifier >= 0x20000000000000000000000000000 ? 113 : 112;

      if (xExponent + msb > yExponent + 16497) { // Overflow
        xExponent = 0x7FFF;
        xSignifier = 0;
      } else if (xExponent + msb + 16380  < yExponent) { // Underflow
        xExponent = 0;
        xSignifier = 0;
      } else if (xExponent + msb + 16268  < yExponent) { // Subnormal
        if (xExponent + 16380 > yExponent)
          xSignifier <<= xExponent + 16380 - yExponent;
        else if (xExponent + 16380 < yExponent)
          xSignifier >>= yExponent - xExponent - 16380;

        xExponent = 0;
      } else { // Normal
        if (msb > 112)
          xSignifier >>= msb - 112;

        xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

        xExponent = xExponent + msb + 16269 - yExponent;
      }

      return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) |
          xExponent << 112 | xSignifier));
    }
  }

  /**
   * Calculate -x.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function neg (bytes16 x) internal pure returns (bytes16) {
    return x ^ 0x80000000000000000000000000000000;
  }

  /**
   * Calculate |x|.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function abs (bytes16 x) internal pure returns (bytes16) {
    return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
  }

  /**
   * Calculate square root of x.  Return NaN on negative x excluding -0.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function sqrt (bytes16 x) internal pure returns (bytes16) {
    if (uint128 (x) >  0x80000000000000000000000000000000) return NaN;
    else {
      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
      if (xExponent == 0x7FFF) return x;
      else {
        uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        if (xExponent == 0) xExponent = 1;
        else xSignifier |= 0x10000000000000000000000000000;

        if (xSignifier == 0) return POSITIVE_ZERO;

        bool oddExponent = xExponent & 0x1 == 0;
        xExponent = xExponent + 16383 >> 1;

        if (oddExponent) {
          if (xSignifier >= 0x10000000000000000000000000000)
            xSignifier <<= 113;
          else {
            uint256 msb = msb (xSignifier);
            uint256 shift = (226 - msb) & 0xFE;
            xSignifier <<= shift;
            xExponent -= shift - 112 >> 1;
          }
        } else {
          if (xSignifier >= 0x10000000000000000000000000000)
            xSignifier <<= 112;
          else {
            uint256 msb = msb (xSignifier);
            uint256 shift = (225 - msb) & 0xFE;
            xSignifier <<= shift;
            xExponent -= shift - 112 >> 1;
          }
        }

        uint256 r = 0x10000000000000000000000000000;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1;
        r = (r + xSignifier / r) >> 1; // Seven iterations should be enough
        uint256 r1 = xSignifier / r;
        if (r1 < r) r = r1;

        return bytes16 (uint128 (xExponent << 112 | r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
      }
    }
  }

  /**
   * Calculate binary logarithm of x.  Return NaN on negative x excluding -0.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function log_2 (bytes16 x) internal pure returns (bytes16) {
    if (uint128 (x) > 0x80000000000000000000000000000000) return NaN;
    else if (x == 0x3FFF0000000000000000000000000000) return POSITIVE_ZERO; 
    else {
      uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
      if (xExponent == 0x7FFF) return x;
      else {
        uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        if (xExponent == 0) xExponent = 1;
        else xSignifier |= 0x10000000000000000000000000000;

        if (xSignifier == 0) return NEGATIVE_INFINITY;

        bool resultNegative;
        uint256 resultExponent = 16495;
        uint256 resultSignifier;

        if (xExponent >= 0x3FFF) {
          resultNegative = false;
          resultSignifier = xExponent - 0x3FFF;
          xSignifier <<= 15;
        } else {
          resultNegative = true;
          if (xSignifier >= 0x10000000000000000000000000000) {
            resultSignifier = 0x3FFE - xExponent;
            xSignifier <<= 15;
          } else {
            uint256 msb = msb (xSignifier);
            resultSignifier = 16493 - msb;
            xSignifier <<= 127 - msb;
          }
        }

        if (xSignifier == 0x80000000000000000000000000000000) {
          if (resultNegative) resultSignifier += 1;
          uint256 shift = 112 - msb (resultSignifier);
          resultSignifier <<= shift;
          resultExponent -= shift;
        } else {
          uint256 bb = resultNegative ? 1 : 0;
          while (resultSignifier < 0x10000000000000000000000000000) {
            resultSignifier <<= 1;
            resultExponent -= 1;
  
            xSignifier *= xSignifier;
            uint256 b = xSignifier >> 255;
            resultSignifier += b ^ bb;
            xSignifier >>= 127 + b;
          }
        }

        return bytes16 (uint128 ((resultNegative ? 0x80000000000000000000000000000000 : 0) |
            resultExponent << 112 | resultSignifier & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
      }
    }
  }

  /**
   * Calculate natural logarithm of x.  Return NaN on negative x excluding -0.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function ln (bytes16 x) internal pure returns (bytes16) {
    return mul (log_2 (x), 0x3FFE62E42FEFA39EF35793C7673007E5);
  }

  /**
   * Calculate 2^x.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function pow_2 (bytes16 x) internal pure returns (bytes16) {
    bool xNegative = uint128 (x) > 0x80000000000000000000000000000000;
    uint256 xExponent = uint128 (x) >> 112 & 0x7FFF;
    uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    if (xExponent == 0x7FFF && xSignifier != 0) return NaN;
    else if (xExponent > 16397)
      return xNegative ? POSITIVE_ZERO : POSITIVE_INFINITY;
    else if (xExponent < 16255)
      return 0x3FFF0000000000000000000000000000;
    else {
      if (xExponent == 0) xExponent = 1;
      else xSignifier |= 0x10000000000000000000000000000;

      if (xExponent > 16367)
        xSignifier <<= xExponent - 16367;
      else if (xExponent < 16367)
        xSignifier >>= 16367 - xExponent;

      if (xNegative && xSignifier > 0x406E00000000000000000000000000000000)
        return POSITIVE_ZERO;

      if (!xNegative && xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        return POSITIVE_INFINITY;

      uint256 resultExponent = xSignifier >> 128;
      xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
      if (xNegative && xSignifier != 0) {
        xSignifier = ~xSignifier;
        resultExponent += 1;
      }

      uint256 resultSignifier = 0x80000000000000000000000000000000;
      if (xSignifier & 0x80000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
      if (xSignifier & 0x40000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
      if (xSignifier & 0x20000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
      if (xSignifier & 0x10000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
      if (xSignifier & 0x8000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
      if (xSignifier & 0x4000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
      if (xSignifier & 0x2000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
      if (xSignifier & 0x1000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
      if (xSignifier & 0x800000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
      if (xSignifier & 0x400000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
      if (xSignifier & 0x200000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
      if (xSignifier & 0x100000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
      if (xSignifier & 0x80000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
      if (xSignifier & 0x40000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
      if (xSignifier & 0x20000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000162E525EE054754457D5995292026 >> 128;
      if (xSignifier & 0x10000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
      if (xSignifier & 0x8000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
      if (xSignifier & 0x4000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
      if (xSignifier & 0x2000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000162E43F4F831060E02D839A9D16D >> 128;
      if (xSignifier & 0x1000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
      if (xSignifier & 0x800000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
      if (xSignifier & 0x400000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
      if (xSignifier & 0x200000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
      if (xSignifier & 0x100000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
      if (xSignifier & 0x80000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
      if (xSignifier & 0x40000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
      if (xSignifier & 0x20000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
      if (xSignifier & 0x10000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
      if (xSignifier & 0x8000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
      if (xSignifier & 0x4000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
      if (xSignifier & 0x2000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
      if (xSignifier & 0x1000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
      if (xSignifier & 0x800000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
      if (xSignifier & 0x400000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
      if (xSignifier & 0x200000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000162E42FEFB2FED257559BDAA >> 128;
      if (xSignifier & 0x100000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
      if (xSignifier & 0x80000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
      if (xSignifier & 0x40000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
      if (xSignifier & 0x20000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
      if (xSignifier & 0x10000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000B17217F7D20CF927C8E94C >> 128;
      if (xSignifier & 0x8000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
      if (xSignifier & 0x4000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000002C5C85FDF477B662B26945 >> 128;
      if (xSignifier & 0x2000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000162E42FEFA3AE53369388C >> 128;
      if (xSignifier & 0x1000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000B17217F7D1D351A389D40 >> 128;
      if (xSignifier & 0x800000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
      if (xSignifier & 0x400000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
      if (xSignifier & 0x200000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000162E42FEFA39FE95583C2 >> 128;
      if (xSignifier & 0x100000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
      if (xSignifier & 0x80000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
      if (xSignifier & 0x40000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000002C5C85FDF473E242EA38 >> 128;
      if (xSignifier & 0x20000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000162E42FEFA39F02B772C >> 128;
      if (xSignifier & 0x10000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
      if (xSignifier & 0x8000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
      if (xSignifier & 0x4000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000002C5C85FDF473DEA871F >> 128;
      if (xSignifier & 0x2000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000162E42FEFA39EF44D91 >> 128;
      if (xSignifier & 0x1000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000B17217F7D1CF79E949 >> 128;
      if (xSignifier & 0x800000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
      if (xSignifier & 0x400000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
      if (xSignifier & 0x200000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000162E42FEFA39EF366F >> 128;
      if (xSignifier & 0x100000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000B17217F7D1CF79AFA >> 128;
      if (xSignifier & 0x80000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
      if (xSignifier & 0x40000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
      if (xSignifier & 0x20000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000162E42FEFA39EF358 >> 128;
      if (xSignifier & 0x10000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000B17217F7D1CF79AB >> 128;
      if (xSignifier & 0x8000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000058B90BFBE8E7BCD5 >> 128;
      if (xSignifier & 0x4000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000002C5C85FDF473DE6A >> 128;
      if (xSignifier & 0x2000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000162E42FEFA39EF34 >> 128;
      if (xSignifier & 0x1000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000B17217F7D1CF799 >> 128;
      if (xSignifier & 0x800000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000058B90BFBE8E7BCC >> 128;
      if (xSignifier & 0x400000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000002C5C85FDF473DE5 >> 128;
      if (xSignifier & 0x200000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000162E42FEFA39EF2 >> 128;
      if (xSignifier & 0x100000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000B17217F7D1CF78 >> 128;
      if (xSignifier & 0x80000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000058B90BFBE8E7BB >> 128;
      if (xSignifier & 0x40000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000002C5C85FDF473DD >> 128;
      if (xSignifier & 0x20000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000162E42FEFA39EE >> 128;
      if (xSignifier & 0x10000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000B17217F7D1CF6 >> 128;
      if (xSignifier & 0x8000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000058B90BFBE8E7A >> 128;
      if (xSignifier & 0x4000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000002C5C85FDF473C >> 128;
      if (xSignifier & 0x2000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000162E42FEFA39D >> 128;
      if (xSignifier & 0x1000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000B17217F7D1CE >> 128;
      if (xSignifier & 0x800000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000058B90BFBE8E6 >> 128;
      if (xSignifier & 0x400000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000002C5C85FDF472 >> 128;
      if (xSignifier & 0x200000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000162E42FEFA38 >> 128;
      if (xSignifier & 0x100000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000B17217F7D1B >> 128;
      if (xSignifier & 0x80000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000058B90BFBE8D >> 128;
      if (xSignifier & 0x40000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000002C5C85FDF46 >> 128;
      if (xSignifier & 0x20000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000162E42FEFA2 >> 128;
      if (xSignifier & 0x10000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000B17217F7D0 >> 128;
      if (xSignifier & 0x8000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000058B90BFBE7 >> 128;
      if (xSignifier & 0x4000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000002C5C85FDF3 >> 128;
      if (xSignifier & 0x2000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000162E42FEF9 >> 128;
      if (xSignifier & 0x1000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000B17217F7C >> 128;
      if (xSignifier & 0x800000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000058B90BFBD >> 128;
      if (xSignifier & 0x400000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000002C5C85FDE >> 128;
      if (xSignifier & 0x200000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000162E42FEE >> 128;
      if (xSignifier & 0x100000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000B17217F6 >> 128;
      if (xSignifier & 0x80000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000058B90BFA >> 128;
      if (xSignifier & 0x40000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000002C5C85FC >> 128;
      if (xSignifier & 0x20000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000162E42FD >> 128;
      if (xSignifier & 0x10000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000B17217E >> 128;
      if (xSignifier & 0x8000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000058B90BE >> 128;
      if (xSignifier & 0x4000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000002C5C85E >> 128;
      if (xSignifier & 0x2000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000162E42E >> 128;
      if (xSignifier & 0x1000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000B17216 >> 128;
      if (xSignifier & 0x800000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000058B90A >> 128;
      if (xSignifier & 0x400000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000002C5C84 >> 128;
      if (xSignifier & 0x200000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000162E41 >> 128;
      if (xSignifier & 0x100000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000B1720 >> 128;
      if (xSignifier & 0x80000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000058B8F >> 128;
      if (xSignifier & 0x40000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000002C5C7 >> 128;
      if (xSignifier & 0x20000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000162E3 >> 128;
      if (xSignifier & 0x10000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000B171 >> 128;
      if (xSignifier & 0x8000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000058B8 >> 128;
      if (xSignifier & 0x4000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000002C5B >> 128;
      if (xSignifier & 0x2000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000162D >> 128;
      if (xSignifier & 0x1000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000B16 >> 128;
      if (xSignifier & 0x800 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000058A >> 128;
      if (xSignifier & 0x400 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000002C4 >> 128;
      if (xSignifier & 0x200 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000161 >> 128;
      if (xSignifier & 0x100 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000000B0 >> 128;
      if (xSignifier & 0x80 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000057 >> 128;
      if (xSignifier & 0x40 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000002B >> 128;
      if (xSignifier & 0x20 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000015 >> 128;
      if (xSignifier & 0x10 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000000A >> 128;
      if (xSignifier & 0x8 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000004 >> 128;
      if (xSignifier & 0x4 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000001 >> 128;

      if (!xNegative) {
        resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        resultExponent += 0x3FFF;
      } else if (resultExponent <= 0x3FFE) {
        resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        resultExponent = 0x3FFF - resultExponent;
      } else {
        resultSignifier = resultSignifier >> resultExponent - 16367;
        resultExponent = 0;
      }

      return bytes16 (uint128 (resultExponent << 112 | resultSignifier));
    }
  }

  /**
   * Calculate e^x.
   *
   * @param x quadruple precision number
   * @return quadruple precision number
   */
  function exp (bytes16 x) internal pure returns (bytes16) {
    return pow_2 (mul (x, 0x3FFF71547652B82FE1777D0FFDA0D23A));
  }

  /**
   * Get index of the most significant non-zero bit in binary representation of
   * x.  Reverts if x is zero.
   *
   * @return index of the most significant non-zero bit in binary representation
   *         of x
   */
  function msb (uint256 x) private pure returns (uint256) {
    require (x > 0);

    uint256 result = 0;

    if (x >= 0x100000000000000000000000000000000) { x >>= 128; result += 128; }
    if (x >= 0x10000000000000000) { x >>= 64; result += 64; }
    if (x >= 0x100000000) { x >>= 32; result += 32; }
    if (x >= 0x10000) { x >>= 16; result += 16; }
    if (x >= 0x100) { x >>= 8; result += 8; }
    if (x >= 0x10) { x >>= 4; result += 4; }
    if (x >= 0x4) { x >>= 2; result += 2; }
    if (x >= 0x2) result += 1; // No need to shift x anymore

    return result;
  }
}

// File: contracts/shared/libraries/Percentages.sol

pragma solidity ^0.7.0;


/**
 * @title Percentage Helpers for Grant Contracts.
 * @dev   Used to offer pro-rata refunds and proportionate payment splitting among grantees
 *        without loss of precision when handling tokens with large supply.
 * @author @NoahMarconi
 */
library Percentages {

    /**
     * @dev Calculate quad point percentage from two uint256 values.
     * @param numerator division numerator.
     * @param denominator division denominator.
     */
    function percentage(uint256 numerator, uint256 denominator)
        internal
        pure
        returns (bytes16)
    {
        bytes16 num = ABDKMathQuad.fromUInt(numerator);
        bytes16 den = ABDKMathQuad.fromUInt(denominator);

        return ABDKMathQuad.div(num, den);
    }

    /**
     * @dev Multiply a quad point percentage by a uint256 value.
     * @param percent percent of total.
     * @param total total to get percent value from.
     */
    function percentTimesTotal(bytes16 percent, uint256 total)
        internal
        pure
        returns (uint256)
    {
        bytes16 tot = ABDKMathQuad.fromUInt(total);
        bytes16 res = ABDKMathQuad.mul(tot, percent);

        return ABDKMathQuad.toUInt(res);
    }

    /**
     * @dev Determine the maxiumum allocation for a Donor or Grantee.
     * @param contribution their contribution to total.
     * @param totalPool total pool to derive percentage owed from.
     * @param remainingPool remaining pool to split between Donors or Grantees.
     */
    function maxAllocation(uint256 contribution, uint256 totalPool, uint256 remainingPool)
        internal
        pure
        returns (uint256)
    {
        bytes16 contributionPercent = Percentages.percentage(
            contribution,
            totalPool
        );

        uint256 contributionMaxAllocation = Percentages.percentTimesTotal(
            contributionPercent,
            remainingPool
        );

        return contributionMaxAllocation;
    }
}

// File: @openzeppelin/contracts/math/SafeMath.sol

pragma solidity ^0.7.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// File: contracts/shared/interfaces/IGrantee.sol

pragma solidity ^0.7.0;

/**
 * @title Grants Spec Abstract Contract.
 * @dev Grant request, funding, and management.
 * @author @NoahMarconi
 */
interface IGrantee {


    /*----------  Global Variable Getters  ----------*/

   /**
     * @dev  Overall funding target for all grantees combined.
     */
    function getCumulativeTargetFunding()
        external
        view
        returns(uint256);

    /**
     * @dev  Grantee amounts are percentage based (if true) or fixed (if false).
     */
    function getPercentageBased()
        external
        view
        returns(bool);

    /*----------  Shared Getters  ----------*/

    /**
     * @dev Get number of grantees.
     * @return number of grantees.
     */
    function getGranteeReferenceLength()
        external
        view
        returns(uint256);

    /**
     * @dev Get grantee address by index.
     * @param index index of grantee to get.
     * @return grantee address.
     */
    function getGranteeReference(uint256 index)
        external
        view
        returns(address);

    /**
     * @dev Get grantee target funding by address.
     * @param grantee address of grantee to set.
     * @return target funding.
     */
    function getGranteeTargetFunding(address grantee)
        external
        view
        returns(uint256);

    /**
     * @dev Get grantee total amount paid by address.
     * @param grantee address of grantee to set.
     * @return total paid.
     */
    function getGranteeTotalPaid(address grantee)
        external
        view
        returns(uint256);

    /**
     * @dev Get grantee payout approved paid by address.
     * @param grantee address of grantee to set.
     * @return payout approved.
     */
    function getGranteePayoutApproved(address grantee)
        external
        view
        returns(uint256);

}

// File: contracts/shared/storage/Grantee.sol

pragma solidity ^0.7.0;

/**
 * @title Grantee State Management Contract.
 * @dev State, getters, and setters for Grantees.
 * @author @NoahMarconi @ameensol @JFickel @ArnaudBrousseau
 */
abstract contract Grantee is IGrantee {

    /*----------  Globals  ----------*/

    mapping(address => uint256) private granteeTargetFunding;  // Funding amount targeted for Grantee.
    mapping(address => uint256) private granteeTotalPaid;      // Cumulative funding received by Grantee.
    mapping(address => uint256) private granteePayoutApproved; // Pending payout approved by Manager.

    address[] private granteeReference;                        // Reference to grantee addresses to allow for iterating over grantees.

    uint256 private cumulativeTargetFunding;                   // Denominator for calculating grantee's percentage.
    bool private percentageBased = false;                      // Grantee amounts are percentage based (if true) or fixed (if false).



    /*----------  Global Variable Getters  ----------*/

   /**
     * @dev  Overall funding target for all grantees combined.
     */
    function getCumulativeTargetFunding()
        public
        view
        override
        returns(uint256)
    {
        return cumulativeTargetFunding;
    }

    /**
     * @dev  Grantee amounts are percentage based (if true) or fixed (if false).
     */
    function getPercentageBased()
        public
        view
        override
        returns(bool)
    {
        return percentageBased;
    }

    /*----------  Global Variable Setters  ----------*/

    /**
     * @dev  Overall funding target for all grantees combined.
     * @param value cumulative target funding to set.
     */
    function setPercentageBased(bool value)
        internal
    {
        percentageBased = value;
    }

    /**
     * @dev  Set grantee targets as either fixed or percentage based.
     * @param value cumulative target funding to set.
     */
    function setCumulativeTargetFunding(uint256 value)
        internal
    {
        cumulativeTargetFunding = value;
    }


    /*----------  Grantee Getters  ----------*/

    /**
     * @dev Get number of grantees.
     * @return number of grantees.
     */
    function getGranteeReferenceLength()
        public
        override
        view
        returns(uint256)
    {
        return granteeReference.length;
    }

    /**
     * @dev Get grantee address by index.
     * @param index index of grantee to get.
     * @return grantee address.
     */
    function getGranteeReference(uint256 index)
        public
        override
        view
        returns(address)
    {
        return granteeReference[index];
    }

    /**
     * @dev Get grantee target funding by address.
     * @param grantee address of grantee to set.
     * @return target funding.
     */
    function getGranteeTargetFunding(address grantee)
        public
        override
        view
        returns(uint256)
    {
        return granteeTargetFunding[grantee];
    }

    /**
     * @dev Get grantee total amount paid by address.
     * @param grantee address of grantee to set.
     * @return total paid.
     */
    function getGranteeTotalPaid(address grantee)
        public
        override
        view
        returns(uint256)
    {
        return granteeTotalPaid[grantee];
    }

    /**
     * @dev Get grantee payout approved paid by address.
     * @param grantee address of grantee to set.
     * @return payout approved.
     */
    function getGranteePayoutApproved(address grantee)
        public
        override
        view
        returns(uint256)
    {
        return granteePayoutApproved[grantee];
    }

    /*----------  Grantee Setters  ----------*/


    /**
     * @dev Add grantee address to reference array.
     * @param grantee grantee address to add.
     */
    function addGranteeReference(address grantee)
        internal
    {
        return granteeReference.push(grantee);
    }

    /**
     * @dev Set grantee target funding by address.
     * @param grantee address of grantee to set.
     * @param value target funding to set.
     */
    function setGranteeTargetFunding(address grantee, uint256 value)
        internal
    {
        granteeTargetFunding[grantee] = value;
    }

    /**
     * @dev Set grantee total amount paid by address.
     * @param grantee address of grantee to set.
     * @param value total paid to set.
     */
    function setGranteeTotalPaid(address grantee, uint256 value)
        internal
    {
        granteeTotalPaid[grantee] = value;
    }

    /**
     * @dev Set grantee payout approved paid by address.
     * @param grantee address of grantee to set.
     * @param value payout approved to set.
     */
    function setGranteePayoutApproved(address grantee, uint256 value)
        internal
    {
        granteePayoutApproved[grantee] = value;
    }

}

// File: contracts/shared/modules/GranteeConstructor.sol

pragma solidity ^0.7.0;

contract GranteeConstructor is Grantee {
    using SafeMath for uint256;

    /*----------  Constructor  ----------*/

    /**
     * @dev Grant creation function. May be called by donors, grantees, or any other relevant party.
     * @param _grantees Sorted recipients of donated funds.
     * @param _amounts Respective allocations for each Grantee (must follow sort order of _grantees).
     * @param _percentageBased Grantee amounts are percentage based (if true) or fixed (if false).
     */
    constructor(
        address[] memory _grantees,
        uint256[] memory _amounts,
        bool _percentageBased
    )
    {

        require(
            _grantees.length > 0,
            "constructor::Invalid Argument. Must have one or more grantees."
        );

        require(
            _grantees.length == _amounts.length,
            "constructor::Invalid Argument. _grantees.length must equal _amounts.length"
        );


        // Initialize Grantees.
        address lastAddress = address(0);
        uint256 _cumulativeTargetFunding = 0;
        for (uint256 i = 0; i < _grantees.length; i++) {
            address currentGrantee = _grantees[i];
            uint256 currentAmount = _amounts[i];

            require(
                currentAmount > 0,
                "constructor::Invalid Argument. currentAmount must be greater than 0."
            );

            require(
                currentGrantee != address(0),
                "constructor::Invalid Argument. grantee address cannot be a ADDRESS_ZERO."
            );

            require(
                currentGrantee > lastAddress,
                "constructor::Invalid Argument. Duplicate or out of order _grantees."
            );


            lastAddress = currentGrantee;
            setGranteeTargetFunding(currentGrantee, currentAmount);

            _cumulativeTargetFunding = _cumulativeTargetFunding.add(currentAmount);

            // Store address as reference.
            addGranteeReference(currentGrantee);
        }

        setCumulativeTargetFunding(_cumulativeTargetFunding);
        setPercentageBased(_percentageBased);

    }

}

// File: contracts/shared/interfaces/IFunding.sol

pragma solidity ^0.7.0;

/**
 * @title Grants Spec Abstract Contract.
 * @dev Grant request, funding, and management.
 * @author @NoahMarconi
 */
interface IFunding {

    /*----------  Events  ----------*/

    /**
     * @dev Funding target reached event.
     */
    event LogFundingComplete();

    /**
     * @dev Grant received funding.
     * @param donor Address funding the grant.
     * @param value Amount in WEI or ATOMIC_UNITS funded.
     */
    event LogFunding(address indexed donor, uint256 value);


    /*----------  Shared Getters  ----------*/

    /**
     * @dev Cumulative funding donated by donors.
     */
    function getTotalFunding()
        external
        view
        returns(uint256);


}

// File: contracts/shared/storage/Funding.sol

pragma solidity ^0.7.0;

/**
 * @title Total Funding.
 * @dev Handles state for tracking contract total amount funded.
 * @author @NoahMarconi @ameensol @JFickel @ArnaudBrousseau
 */
abstract contract Funding is IFunding {
    using SafeMath for uint256;


    /*----------  Globals  ----------*/

    /* solhint-disable max-line-length */
    uint256 private totalFunding;                 // Cumulative funding donated by donors.
    /* solhint-enable max-line-length */


    /*----------  Shared Getters  ----------*/

    /**
     * @dev Cumulative funding donated by donors.
     */
    function getTotalFunding()
        public
        override
        view
        returns(uint256)
    {
        return totalFunding;
    }


    /*----------  Shared Setters  ----------*/

    /**
     * @dev Increase cumulative funding donated by donors.
     * @param value amount to increase total funding by.
     */
    function increaseTotalFundingBy(uint256 value)
        internal
    {
        totalFunding = totalFunding.add(value);
    }

    function setTotalFunding(uint256 value)
        internal
    {
        totalFunding = value;
    }

}

// File: contracts/shared/interfaces/IBaseGrant.sol

pragma solidity ^0.7.0;

/**
 * @title Grants Spec Abstract Contract.
 * @dev Grant request, funding, and management.
 * @author @NoahMarconi
 */
interface IBaseGrant {

    /*----------  Events  ----------*/

    /**
     * @dev Funding target reached event.
     * implemented in IFunding
     * event LogFundingComplete();
     */

    /**
     * @dev Grant received funding.
     * implemented in IFunding
     * @param donor Address funding the grant.
     * @param value Amount in WEI or ATOMIC_UNITS funded.
     * event LogFunding(address indexed donor, uint256 value);
     */

    /**
     * @dev Grant paying grantee.
     * @param grantee Address receiving payment.
     * @param value Amount in WEI or ATOMIC_UNITS paid.
     */
    event LogPayment(address indexed grantee, uint256 value);


    /*----------  Shared Getters  ----------*/

    /**
     * @dev URI for additional (off-chain) grant details such as description, milestones, etc.
     */
    function getUri()
        external
        view
        returns(bytes32);

    /**
     * @dev If null, amount is in wei, otherwise address of ERC20-compliant contract.
     */
    function getCurrency()
        external
        view
        returns(address);

    /**
     * @dev Funding threshold required to begin releasing funds.
     */
    function getTargetFunding()
        external
        view
        returns(uint256);

    /**
     * @dev Cumulative funding paid to grantees.
     */
    function getTotalPaid()
        external
        view
        returns(uint256);

    /**
     * @dev Date after which signal OR funds cannot be sent.
     */
    function getFundingDeadline()
        external
        view
        returns(uint256);

    /**
     * @dev Date after which payouts must be complete or anyone can trigger refunds.
     */
    function getContractExpiration()
        external
        view
        returns(uint256);

    /**
     * @dev Flag to indicate when grant is cancelled.
     */
    function getGrantCancelled()
        external
        view
        returns(bool);

}

// File: contracts/shared/storage/BaseGrant.sol

pragma solidity ^0.7.0;

/**
 * @title Base Grant State Management Contract.
 * @dev State, getters, and setters for BaseGrant.
 * @author @NoahMarconi @ameensol @JFickel @ArnaudBrousseau
 */
abstract contract BaseGrant is IBaseGrant {

    /*----------  Globals  ----------*/

    /* solhint-disable max-line-length */
    bytes32 private uri;                            // URI for additional (off-chain) grant details such as description, milestones, etc.
    address private currency;                     // (Optional) If null, amount is in wei, otherwise address of ERC20-compliant contract.
    uint256 private targetFunding;                // (Optional) Funding threshold required to begin releasing funds.
    uint256 private totalPaid;                    // Cumulative funding paid to grantees.
    uint256 private fundingDeadline;              // (Optional) Date after which signal OR funds cannot be sent.
    uint256 private contractExpiration;           // (Optional) Date after which payouts must be complete or anyone can trigger refunds.
    bool private grantCancelled;                  // Flag to indicate when grant is cancelled.
    /* solhint-enable max-line-length */


    /*----------  Shared Getters  ----------*/

    function getUri()
        public
        override
        view
        returns(bytes32)
    {
        return uri;
    }

    function getContractExpiration()
        public
        override
        view
        returns(uint256)
    {
        return contractExpiration;
    }

    function getFundingDeadline()
        public
        override
        view
        returns(uint256)
    {
        return fundingDeadline;
    }

    function getTargetFunding()
        public
        override
        view
        returns(uint256)
    {
        return targetFunding;
    }

    function getTotalPaid()
        public
        override
        view
        returns(uint256)
    {
        return totalPaid;
    }

    function getGrantCancelled()
        public
        override
        view
        returns(bool)
    {
        return grantCancelled;
    }

    function getCurrency()
        public
        override
        view
        returns(address)
    {
        return currency;
    }

    /*----------  Shared Setters  ----------*/

    function setTotalPaid(uint256 value)
        internal
    {
        totalPaid = value;
    }

    function setUri(bytes32 value)
        internal
    {
        uri = value;
    }

    function setGrantCancelled(bool value)
        internal
    {
        grantCancelled = value;
    }
}

// File: contracts/UnmanagedGrant.sol

pragma solidity ^0.7.0;

/**
 * @title Grant for Eth2.
 * @dev Managed                     (n)
 *      Funding Deadline            (n)
 *      Contract expiry             (n)
 *      With Token                  (n)
 *      Percentage based allocation (y)
 *      Withdraw (pull payment)     (n)
 *      This is a simplified grant which behaves as a simple payment splitter.
 *      No refunds or managers; payment are immediately pushed.
 *      WARNING: vulnerable to sending to Gas Token generating addresses. Trust in grantees not doing so is required.
 * @author @NoahMarconi
 */
contract UnmanagedGrant is ReentrancyGuard, BaseGrant, GranteeConstructor, Funding {


    /*----------  Constructor  ----------*/

    /**
     * @dev Grant creation function. May be called by grantors, grantees, or any other relevant party.
     * @param _grantees Sorted recipients of unlocked funds.
     * @param _amounts Respective allocations for each Grantee (must follow sort order of _grantees).
     * @param _uri URI for additional (off-chain) grant details such as description, milestones, etc.
     */
    constructor(
        address[] memory _grantees,
        uint256[] memory _amounts,
        bytes32 _uri
    )
        GranteeConstructor(_grantees, _amounts, true)
    {

        // Initialize globals.
        setUri(_uri);

    }


    /*----------  Fallback  ----------*/

    receive()
        external
        payable
        nonReentrant
    {

        require(
            msg.value > 0,
            "fallback::Invalid Value. msg.value must be greater than 0."
        );

        uint256 numGrantees = getGranteeReferenceLength();
        address lastGrantee = payable(getGranteeReference(numGrantees - 1));
        for (uint256 i = 0; i < numGrantees; i++) {
            address payable currentGrantee = payable(getGranteeReference(i));

            uint256 eligiblePortion = Percentages.maxAllocation(
                getGranteeTargetFunding(currentGrantee),
                getCumulativeTargetFunding(),
                msg.value
            );

            if (currentGrantee == lastGrantee) {
                // Handle rounding of a few wei.
                // @audit question for auditor, should we enforce this is within expected threshold?
                eligiblePortion = address(this).balance;
            }

            if (eligiblePortion > 0) {
                (bool success, ) = currentGrantee.call{ value: eligiblePortion}("");
                require(
                    success,
                    "fallback::Transfer Error. Unable to send eligiblePortion to Grantee."
                );
                emit LogPayment(currentGrantee, eligiblePortion);
            }

        }

        increaseTotalFundingBy(msg.value);

        emit LogFunding(msg.sender, msg.value);

    }

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address[]","name":"_grantees","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"bytes32","name":"_uri","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"donor","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogFunding","type":"event"},{"anonymous":false,"inputs":[],"name":"LogFundingComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"grantee","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogPayment","type":"event"},{"inputs":[],"name":"getContractExpiration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCumulativeTargetFunding","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrency","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFundingDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGrantCancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"grantee","type":"address"}],"name":"getGranteePayoutApproved","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getGranteeReference","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGranteeReferenceLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"grantee","type":"address"}],"name":"getGranteeTargetFunding","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"grantee","type":"address"}],"name":"getGranteeTotalPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPercentageBased","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTargetFunding","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFunding","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUri","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

Deployed Bytecode

0x6080604052600436106100ec5760003560e01c80638025220e1161008a578063c569c96811610059578063c569c96814610612578063d6b3798a14610677578063fa7e64e9146106a2578063fedc58e314610707576103e0565b80638025220e1461052a578063b1039e2814610557578063b6e3a3ff14610582578063c2750f99146105e7576103e0565b806356b6491a116100c657806356b6491a146104685780636133c27c146104935780636793141f146104be5780636945c1fd146104e9576103e0565b80630f5a89c8146103e557806337e44469146104125780634e16fc8b1461043d576103e0565b366103e0576002600054141561016a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081525060200191505060405180910390fd5b6002600081905550600034116101cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a815260200180611652603a913960400191505060405180910390fd5b60006101d561076c565b905060006101e560018303610779565b905060005b8281101561037c5760006101fd82610779565b9050600061021b61020d836107ba565b610215610803565b3461080d565b90508373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610255574790505b600081111561036d5760008273ffffffffffffffffffffffffffffffffffffffff168260405180600001905060006040518083038185875af1925050503d80600081146102be576040519150601f19603f3d011682016040523d82523d6000602084013e6102c3565b606091505b505090508061031d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604481526020018061160e6044913960600191505060405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff167f27a391d95d67e3626574fb5fbe3532bb7366e9254957b1f0e840953c248b2aa8836040518082815260200191505060405180910390a2505b505080806001019150506101ea565b5061038634610836565b3373ffffffffffffffffffffffffffffffffffffffff167f9f1a5e1a5d3381f9af1a62f8d61e4ae71444e28af488786cb10c8b2b457632ae346040518082815260200191505060405180910390a250506001600081905550005b600080fd5b3480156103f157600080fd5b506103fa610854565b60405180821515815260200191505060405180910390f35b34801561041e57600080fd5b5061042761076c565b6040518082815260200191505060405180910390f35b34801561044957600080fd5b5061045261086b565b6040518082815260200191505060405180910390f35b34801561047457600080fd5b5061047d610875565b6040518082815260200191505060405180910390f35b34801561049f57600080fd5b506104a8610803565b6040518082815260200191505060405180910390f35b3480156104ca57600080fd5b506104d361087f565b6040518082815260200191505060405180910390f35b3480156104f557600080fd5b506104fe610889565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053657600080fd5b5061053f6108b3565b60405180821515815260200191505060405180910390f35b34801561056357600080fd5b5061056c6108ca565b6040518082815260200191505060405180910390f35b34801561058e57600080fd5b506105bb600480360360208110156105a557600080fd5b8101908080359060200190929190505050610779565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105f357600080fd5b506105fc6108d4565b6040518082815260200191505060405180910390f35b34801561061e57600080fd5b506106616004803603602081101561063557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108de565b6040518082815260200191505060405180910390f35b34801561068357600080fd5b5061068c610927565b6040518082815260200191505060405180910390f35b3480156106ae57600080fd5b506106f1600480360360208110156106c557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610931565b6040518082815260200191505060405180910390f35b34801561071357600080fd5b506107566004803603602081101561072a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107ba565b6040518082815260200191505060405180910390f35b6000600b80549050905090565b6000600b828154811061078857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600c54905090565b60008061081a8585610a02565b905060006108288285610a31565b905080925050509392505050565b61084b81600e5461097a90919063ffffffff16565b600e8190555050565b6000600d60009054906101000a900460ff16905090565b6000600154905090565b6000600554905090565b6000600454905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600760009054906101000a900460ff16905090565b6000600654905090565b6000600e54905090565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600354905090565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000808284019050838110156109f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600080610a0e84610a60565b90506000610a1b84610a60565b9050610a278282610ade565b9250505092915050565b600080610a3d83610a60565b90506000610a4b8286610f99565b9050610a568161142e565b9250505092915050565b600080821415610a7657600060801b9050610ad9565b60008290506000610a868261152c565b90506070811015610a9f578060700382901b9150610ab3565b6070811115610ab2576070810382901c91505b5b607081613fff01901b6dffffffffffffffffffffffffffff83161791508160801b925050505b919050565b600080617fff60708560801c6fffffffffffffffffffffffffffffffff16901c166fffffffffffffffffffffffffffffffff1690506000617fff60708560801c6fffffffffffffffffffffffffffffffff16901c166fffffffffffffffffffffffffffffffff169050617fff821415610b9957617fff811415610b78576f7fff800000000000000000000000000060801b92505050610f93565b6f8000000000000000000000000000000060801b8416851892505050610f93565b617fff811415610c1857600060801b6dffffffffffffffffffffffffffff60801b85166fffffffffffffffffffffffffffffffff191614610bf1576f7fff800000000000000000000000000060801b92505050610f93565b6f8000000000000000000000000000000060801b84861816600060801b1792505050610f93565b600060801b6f7fffffffffffffffffffffffffffffff60801b85166fffffffffffffffffffffffffffffffff19161415610cd357600060801b6f7fffffffffffffffffffffffffffffff60801b86166fffffffffffffffffffffffffffffffff19161415610c9d576f7fff800000000000000000000000000060801b92505050610f93565b6f8000000000000000000000000000000060801b848618166f7fff000000000000000000000000000060801b1792505050610f93565b60006dffffffffffffffffffffffffffff8560801c166fffffffffffffffffffffffffffffffff1690506000821415610d0f5760019150610d24565b6e010000000000000000000000000000811790505b60006dffffffffffffffffffffffffffff8760801c166fffffffffffffffffffffffffffffffff1690506000841415610d885760008114610d83576000610d6a8261152c565b60e20390508082901b9150600194506072810384019350505b610da1565b60726e0100000000000000000000000000008217901b90505b818181610daa57fe5b0490506000811415610e1557600060801b6f8000000000000000000000000000000060801b878918166fffffffffffffffffffffffffffffffff191611610df557600060801b610e0a565b6f8000000000000000000000000000000060801b5b945050505050610f93565b6d1000000000000000000000000000811015610e2d57fe5b60006e080000000000000000000000000000821015610e8e576e040000000000000000000000000000821015610e83576e020000000000000000000000000000821015610e7b576070610e7e565b60715b610e86565b60725b60ff16610e98565b610e978261152c565b5b905061407184018186011115610eb657617fff945060009150610f53565b83613ffc828701011015610ed1576000945060009150610f52565b83613f8c828701011015610f1f5783613ffc86011115610efc5783613ffc86010382901b9150610f16565b83613ffc86011015610f1557613ffc8585030382901c91505b5b60009450610f51565b6070811115610f32576070810382901c91505b6dffffffffffffffffffffffffffff8216915083613f8d828701010394505b5b5b81607086901b6f8000000000000000000000000000000060801b898b181660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b600080617fff60708560801c6fffffffffffffffffffffffffffffffff16901c166fffffffffffffffffffffffffffffffff1690506000617fff60708560801c6fffffffffffffffffffffffffffffffff16901c166fffffffffffffffffffffffffffffffff169050617fff82141561113057617fff8114156110be57836fffffffffffffffffffffffffffffffff1916856fffffffffffffffffffffffffffffffff19161415611065576f8000000000000000000000000000000060801b8416851892505050611428565b6f8000000000000000000000000000000060801b8486186fffffffffffffffffffffffffffffffff191614156110a15783851792505050611428565b6f7fff800000000000000000000000000060801b92505050611428565b600060801b6f7fffffffffffffffffffffffffffffff60801b85166fffffffffffffffffffffffffffffffff1916141561110f576f7fff800000000000000000000000000060801b92505050611428565b6f8000000000000000000000000000000060801b8416851892505050611428565b617fff8114156111ac57600060801b6f7fffffffffffffffffffffffffffffff60801b86166fffffffffffffffffffffffffffffffff1916141561118b576f7fff800000000000000000000000000060801b92505050611428565b6f8000000000000000000000000000000060801b8516841892505050611428565b60006dffffffffffffffffffffffffffff8660801c166fffffffffffffffffffffffffffffffff16905060008314156111e857600192506111fd565b6e010000000000000000000000000000811790505b60006dffffffffffffffffffffffffffff8660801c166fffffffffffffffffffffffffffffffff1690506000831415611239576001925061124e565b6e010000000000000000000000000000811790505b808202915060008214156112bb57600060801b6f8000000000000000000000000000000060801b878918166fffffffffffffffffffffffffffffffff19161161129b57600060801b6112b0565b6f8000000000000000000000000000000060801b5b945050505050611428565b828401935060007c0200000000000000000000000000000000000000000000000000000000831015611322577c010000000000000000000000000000000000000000000000000000000083101561131a576113158361152c565b61131d565b60e05b611325565b60e15b905061407081860110156113405760009450600092506113e8565b6140e081860110156113845761407085101561136557846140700383901c925061137b565b61407085111561137a57614070850383901b92505b5b600094506113e7565b61c0dd818601111561139e57617fff9450600092506113e6565b60708111156113b5576070810383901c92506113c9565b60708110156113c8578060700383901b92505b5b6dffffffffffffffffffffffffffff831692506140df8186010394505b5b5b82607086901b6f8000000000000000000000000000000060801b898b181660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b600080617fff60708460801c6fffffffffffffffffffffffffffffffff16901c166fffffffffffffffffffffffffffffffff169050613fff811015611477576000915050611527565b6f800000000000000000000000000000008360801c6fffffffffffffffffffffffffffffffff16106114a857600080fd5b6140fe8111156114b757600080fd5b60006e0100000000000000000000000000006dffffffffffffffffffffffffffff8560801c6fffffffffffffffffffffffffffffffff161617905061406f82101561150b578161406f0381901c9050611521565b61406f8211156115205761406f820381901b90505b5b80925050505b919050565b600080821161153a57600080fd5b6000700100000000000000000000000000000000831061156257608083901c92506080810190505b68010000000000000000831061158057604083901c92506040810190505b640100000000831061159a57602083901c92506020810190505b6201000083106115b257601083901c92506010810190505b61010083106115c957600883901c92506008810190505b601083106115df57600483901c92506004810190505b600483106115f557600283901c92506002810190505b60028310611604576001810190505b8091505091905056fe66616c6c6261636b3a3a5472616e73666572204572726f722e20556e61626c6520746f2073656e6420656c696769626c65506f7274696f6e20746f204772616e7465652e66616c6c6261636b3a3a496e76616c69642056616c75652e206d73672e76616c7565206d7573742062652067726561746572207468616e20302ea26469706673582212201e359ce3af9b33be3973cdf8fcde49672f5e67bec1c2ad411774b420daf62ef964736f6c63430007000033

Deployed Bytecode Sourcemap

79017:2301:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1837:1;2434:7;;:19;;2426:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1837:1;2567:7;:18;;;;79963:1:::1;79951:9;:13;79929:121;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80063:19;80085:27;:25;:27::i;:::-;80063:49;;80123:19;80153:36;80187:1;80173:11;:15;80153:19;:36::i;:::-;80123:67;;80206:9;80201:1006;80225:11;80221:1;:15;80201:1006;;;80258:30;80299:22;80319:1;80299:19;:22::i;:::-;80258:64;;80339:23;80365:173;80409:39;80433:14;80409:23;:39::i;:::-;80467:28;:26;:28::i;:::-;80514:9;80365:25;:173::i;:::-;80339:199;;80577:11;80559:29;;:14;:29;;;80555:261;;;80779:21;80761:39;;80555:261;80854:1;80836:15;:19;80832:362;;;80877:12;80895:14;:19;;80923:15;80895:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80876:67;;;80992:7;80962:149;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81146:14;81135:43;;;81162:15;81135:43;;;;;;;;;;;;;;;;;;80832:362;;80201:1006;;80238:3;;;;;;;80201:1006;;;;81219:33;81242:9;81219:22;:33::i;:::-;81281:10;81270:33;;;81293:9;81270:33;;;;;;;;;;;;;;;;;;2598:1;;1793::::0;2746:7;:22;;;;79017:2301;;;;;65413:147;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;66297:165;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;76968:126;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;77266:150;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;65139:166;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;77578:138;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;77877:136;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;77724:145;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;77102:156;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;66610:172;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;72843:144;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;67628:186;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;77424:146;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;67285:176;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;66942:184;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;66297:165;66399:7;66431:16;:23;;;;66424:30;;66297:165;:::o;66610:172::-;66719:7;66751:16;66768:5;66751:23;;;;;;;;;;;;;;;;;;;;;;;;;66744:30;;66610:172;;;:::o;66942:184::-;67057:7;67089:20;:29;67110:7;67089:29;;;;;;;;;;;;;;;;67082:36;;66942:184;;;:::o;65139:166::-;65242:7;65274:23;;65267:30;;65139:166;:::o;56110:480::-;56247:7;56272:27;56302:84;56339:12;56366:9;56302:22;:84::i;:::-;56272:114;;56399:33;56435:102;56479:19;56513:13;56435:29;:102::i;:::-;56399:138;;56557:25;56550:32;;;;56110:480;;;;;:::o;73183:127::-;73279:23;73296:5;73279:12;;:16;;:23;;;;:::i;:::-;73264:12;:38;;;;73183:127;:::o;65413:147::-;65508:4;65537:15;;;;;;;;;;;65530:22;;65413:147;:::o;76968:126::-;77051:7;77083:3;;77076:10;;76968:126;:::o;77266:150::-;77361:7;77393:15;;77386:22;;77266:150;:::o;77578:138::-;77667:7;77699:9;;77692:16;;77578:138;:::o;77877:136::-;77965:7;77997:8;;;;;;;;;;;77990:15;;77877:136;:::o;77724:145::-;77818:4;77847:14;;;;;;;;;;;77840:21;;77724:145;:::o;77102:156::-;77200:7;77232:18;;77225:25;;77102:156;:::o;72843:144::-;72935:7;72967:12;;72960:19;;72843:144;:::o;67628:186::-;67744:7;67776:21;:30;67798:7;67776:30;;;;;;;;;;;;;;;;67769:37;;67628:186;;;:::o;77424:146::-;77517:7;77549:13;;77542:20;;77424:146;:::o;67285:176::-;67396:7;67428:16;:25;67445:7;67428:25;;;;;;;;;;;;;;;;67421:32;;67285:176;;;:::o;57518:181::-;57576:7;57596:9;57612:1;57608;:5;57596:17;;57637:1;57632;:6;;57624:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57690:1;57683:8;;;57518:181;;;;:::o;55043:294::-;55153:7;55178:11;55192:32;55214:9;55192:21;:32::i;:::-;55178:46;;55235:11;55249:34;55271:11;55249:21;:34::i;:::-;55235:48;;55303:26;55320:3;55325;55303:16;:26::i;:::-;55296:33;;;;55043:294;;;;:::o;55524:283::-;55633:7;55658:11;55672:28;55694:5;55672:21;:28::i;:::-;55658:42;;55711:11;55725:30;55742:3;55747:7;55725:16;:30::i;:::-;55711:44;;55775:24;55795:3;55775:19;:24::i;:::-;55768:31;;;;55524:283;;;;:::o;5880:405::-;5933:7;5958:1;5953;:6;5949:331;;;5977:1;5968:11;;5961:18;;;;5949:331;6000:14;6017:1;6000:18;;6029:11;6043:12;6048:6;6043:3;:12::i;:::-;6029:26;;6074:3;6068;:9;6064:84;;;6096:3;6090;:9;6079:20;;;;;6064:84;;;6123:3;6117;:9;6113:35;;;6145:3;6139;:9;6128:20;;;;;6113:35;6064:84;6225:3;6218;6210:5;:11;:18;;6177:30;6168:6;:39;:60;6159:69;;6264:6;6246:26;;6239:33;;;;5880:405;;;;:::o;27500:2698::-;27559:7;27575:17;27616:6;27610:3;27604:1;27595:11;;:18;;;;:27;27575:47;;;;27629:17;27670:6;27664:3;27658:1;27649:11;;:18;;;;:27;27629:47;;;;27702:6;27689:9;:19;27685:2508;;;27736:6;27723:9;:19;27719:98;;;3849:34;27751:3;;27744:10;;;;;;27719:98;27783:34;27779:38;;:1;:38;27775:1;:42;27768:49;;;;;;27685:2508;27848:6;27835:9;:19;27831:2362;;;27911:1;27869:43;;27873:34;27869:38;;:1;:38;:43;;;;27865:140;;3849:34;27921:3;;27914:10;;;;;;27865:140;27971:34;27961:44;;27966:1;27962;:5;27961:44;3400:34;27945:13;;:60;27938:67;;;;;;27831:2362;28065:1;28023:43;;28027:34;28023:38;;:1;:38;:43;;;;28019:2174;;;28123:1;28081:43;;28085:34;28081:38;;:1;:38;:43;;;;28077:144;;;3849:34;28133:3;;28126:10;;;;;;28077:144;28187:34;28177:44;;28182:1;28178;:5;28177:44;3621:34;28157:17;;:64;28150:71;;;;;;28019:2174;28244:18;28279:30;28274:1;28265:11;;:44;28244:65;;;;28335:1;28322:9;:14;28318:92;;;28350:1;28338:13;;28318:92;;;28379:31;28365:45;;;;28318:92;28421:18;28456:30;28451:1;28442:11;;:44;28421:65;;;;28512:1;28499:9;:14;28495:321;;;28544:1;28530:10;:15;28526:181;;28560:10;28579:16;28584:10;28579:3;:16::i;:::-;28573:3;:22;28560:35;;28625:5;28610:20;;;;;28657:1;28645:13;;28692:3;28684:5;:11;28671:24;;;;28526:181;;28495:321;;;28803:3;28767:31;28754:10;:44;28753:53;;28740:66;;28495:321;28852:10;28839;:23;;;;;;28826:36;;28889:1;28875:10;:15;28871:130;;;28955:1;28908:48;;28918:34;28908:44;;28913:1;28909;:5;28908:44;:48;;;;:93;;3400:34;28988:13;;28908:93;;;3505:34;28972:13;;28908:93;28901:100;;;;;;;;28871:130;29034:30;29020:10;:44;;29012:53;;;;29076:11;29113:31;29099:10;:45;;:196;;29189:31;29175:10;:45;;:120;;29252:31;29238:10;:45;;:57;;29292:3;29238:57;;;29286:3;29238:57;29175:120;;;29223:3;29175:120;29099:196;;;;;29147:16;29152:10;29147:3;:16::i;:::-;29099:196;29076:219;;29340:5;29328:9;:17;29322:3;29310:9;:15;:35;29306:745;;;29382:6;29370:18;;29412:1;29399:14;;29306:745;;;29460:9;29451:5;29445:3;29433:9;:15;:23;:36;29429:622;;;29507:1;29495:13;;29532:1;29519:14;;29429:622;;;29580:9;29571:5;29565:3;29553:9;:15;:23;:36;29549:502;;;29639:9;29631:5;29619:9;:17;:29;29615:196;;;29696:9;29688:5;29676:9;:17;:29;29661:44;;;;;29615:196;;;29745:9;29737:5;29725:9;:17;:29;29721:90;;;29806:5;29794:9;29782;:21;:29;29767:44;;;;;29721:90;29615:196;29836:1;29824:13;;29549:502;;;29884:3;29878;:9;29874:50;;;29921:3;29915;:9;29900:24;;;;;29874:50;29951:30;29937:44;;;;30032:9;30024:5;30018:3;30006:9;:15;:23;:35;29994:47;;29549:502;29429:622;29306:745;30173:10;30167:3;30154:9;:16;;30105:34;30095:44;;30100:1;30096;:5;30095:44;30086:54;;:84;;;:97;30068:117;;30061:124;;;;;;;27500:2698;;;;;:::o;23802:2405::-;23861:7;23877:17;23918:6;23912:3;23906:1;23897:11;;:18;;;;:27;23877:47;;;;23931:17;23972:6;23966:3;23960:1;23951:11;;:18;;;;:27;23931:47;;;;24004:6;23991:9;:19;23987:2215;;;24038:6;24025:9;:19;24021:361;;;24066:1;24061:6;;;:1;:6;;;;24057:164;;;24084:34;24080:38;;:1;:38;24076:1;:42;24069:49;;;;;;24057:164;24147:34;24138:43;;24142:1;24138;:5;:43;;;;24134:87;;;24194:1;24190;:5;24183:12;;;;;;24134:87;3849:34;24218:3;;24211:10;;;;;;24021:361;24294:1;24252:43;;24256:34;24252:38;;:1;:38;:43;;;;24248:124;;;3849:34;24304:3;;24297:10;;;;;;24248:124;24338:34;24334:38;;:1;:38;24330:1;:42;24323:49;;;;;;23987:2215;24412:6;24399:9;:19;24395:1807;;;24477:1;24435:43;;24439:34;24435:38;;:1;:38;:43;;;;24431:124;;;3849:34;24487:3;;24480:10;;;;;;24431:124;24521:34;24517:38;;:1;:38;24513:1;:42;24506:49;;;;;;24395:1807;24578:18;24613:30;24608:1;24599:11;;:44;24578:65;;;;24669:1;24656:9;:14;24652:92;;;24684:1;24672:13;;24652:92;;;24713:31;24699:45;;;;24652:92;24755:18;24790:30;24785:1;24776:11;;:44;24755:65;;;;24846:1;24833:9;:14;24829:92;;;24861:1;24849:13;;24829:92;;;24890:31;24876:45;;;;24829:92;24946:10;24932:24;;;;24983:1;24969:10;:15;24965:130;;;25049:1;25002:48;;25012:34;25002:44;;25007:1;25003;:5;25002:44;:48;;;;:93;;3400:34;25082:13;;25002:93;;;3505:34;25066:13;;25002:93;24995:100;;;;;;;;24965:130;25119:9;25106:22;;;;25139:11;25176:59;25162:10;:73;;:198;;25267:59;25253:10;:73;;:107;;25344:16;25349:10;25344:3;:16::i;:::-;25253:107;;;25329:3;25253:107;25162:198;;;25238:3;25162:198;25139:221;;25393:5;25387:3;25375:9;:15;:23;25371:689;;;25436:1;25424:13;;25461:1;25448:14;;25371:689;;;25500:5;25494:3;25482:9;:15;:23;25478:582;;;25547:5;25535:9;:17;25531:148;;;25588:9;25580:5;:17;25565:32;;;;;25531:148;;;25629:5;25617:9;:17;25613:66;;;25674:5;25662:9;:17;25647:32;;;;;25613:66;25531:148;25702:1;25690:13;;25478:582;;;25741:5;25735:3;25723:9;:15;:23;25719:341;;;25771:6;25759:18;;25801:1;25788:14;;25719:341;;;25839:3;25833;:9;25829:116;;;25876:3;25870;:9;25855:24;;;;;25829:116;;;25905:3;25899;:9;25895:50;;;25942:3;25936;:9;25921:24;;;;;25895:50;25829:116;25972:30;25958:44;;;;26045:5;26039:3;26027:9;:15;:23;26015:35;;25719:341;25478:582;25371:689;26182:10;26176:3;26163:9;:16;;26114:34;26104:44;;26109:1;26105;:5;26104:44;26095:54;;:84;;;:97;26077:117;;26070:124;;;;;;;23802:2405;;;;;:::o;6693:558::-;6744:7;6760:16;6800:6;6794:3;6788:1;6779:11;;:18;;;;:27;6760:46;;;;6830:5;6819:8;:16;6815:30;;;6844:1;6837:8;;;;;6815:30;6890:34;6885:1;6876:11;;:48;;;6867:58;;;;;;6967:5;6955:8;:17;;6946:27;;;;;;6992:14;7073:31;7033:30;7027:1;7018:11;;7009:21;;:54;:95;6992:112;;7128:5;7117:8;:16;7113:110;;;7154:8;7146:5;:16;7135:27;;;;;7113:110;;;7189:5;7178:8;:16;7174:49;;;7218:5;7207:8;:16;7196:27;;;;;7174:49;7113:110;7239:6;7232:13;;;;6693:558;;;;:::o;53900:585::-;53947:7;53976:1;53972;:5;53963:15;;;;;;53987:14;54023:35;54018:1;:40;54014:75;;54068:3;54062:9;;;;;54083:3;54073:13;;;;54014:75;54104:19;54099:1;:24;54095:57;;54133:2;54127:8;;;;;54147:2;54137:12;;;;54095:57;54167:11;54162:1;:16;54158:49;;54188:2;54182:8;;;;;54202:2;54192:12;;;;54158:49;54222:7;54217:1;:12;54213:45;;54239:2;54233:8;;;;;54253:2;54243:12;;;;54213:45;54273:5;54268:1;:10;54264:41;;54288:1;54282:7;;;;;54301:1;54291:11;;;;54264:41;54320:4;54315:1;:9;54311:40;;54334:1;54328:7;;;;;54347:1;54337:11;;;;54311:40;54366:3;54361:1;:8;54357:39;;54379:1;54373:7;;;;;54392:1;54382:11;;;;54357:39;54411:3;54406:1;:8;54402:25;;54426:1;54416:11;;;;54402:25;54473:6;54466:13;;;53900:585;;;:::o

Swarm Source

ipfs://1e359ce3af9b33be3973cdf8fcde49672f5e67bec1c2ad411774b420daf62ef9

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.