MATIC Price: $0.99 (-2.67%)
Gas: 130 GWei
 
Transaction Hash
Method
Block
From
To
Value
Donate209120492021-11-02 22:16:39877 days ago1635891399IN
0xea195300...7e4e2BAf3
5 MATIC0.0047414130
Donate208222412021-10-31 14:21:01879 days ago1635690061IN
0xea195300...7e4e2BAf3
0 MATIC0.0114301230
Donate208171382021-10-31 11:14:37879 days ago1635678877IN
0xea195300...7e4e2BAf3
0.1 MATIC0.000986496
Donate207636132021-10-30 2:48:33881 days ago1635562113IN
0xea195300...7e4e2BAf3
15 MATIC0.0065657730
Donate207265232021-10-29 3:49:28882 days ago1635479368IN
0xea195300...7e4e2BAf3
0 MATIC0.0033586840
Donate207187832021-10-28 22:34:16882 days ago1635460456IN
0xea195300...7e4e2BAf3
10 MATIC0.0057899730
Donate207175872021-10-28 21:44:40882 days ago1635457480IN
0xea195300...7e4e2BAf3
2 MATIC0.0049328130
Donate207174132021-10-28 21:38:40882 days ago1635457120IN
0xea195300...7e4e2BAf3
5 MATIC0.000318011.934064
Donate207164222021-10-28 20:59:54882 days ago1635454794IN
0xea195300...7e4e2BAf3
6 MATIC0.0065654130
Donate207163902021-10-28 20:58:46882 days ago1635454726IN
0xea195300...7e4e2BAf3
0 MATIC0.0034087830
Donate207162952021-10-28 20:55:32882 days ago1635454532IN
0xea195300...7e4e2BAf3
15 MATIC0.0081103230
Donate207160892021-10-28 20:43:56882 days ago1635453836IN
0xea195300...7e4e2BAf3
0 MATIC0.000345932
Donate207160192021-10-28 20:40:50882 days ago1635453650IN
0xea195300...7e4e2BAf3
0 MATIC0.0051890430
Donate207159552021-10-28 20:38:38882 days ago1635453518IN
0xea195300...7e4e2BAf3
0 MATIC0.0065244630
Donate206708612021-10-27 14:44:05883 days ago1635345845IN
0xea195300...7e4e2BAf3
0 MATIC0.0058411530
Donate206018482021-10-25 16:49:30885 days ago1635180570IN
0xea195300...7e4e2BAf3
160 MATIC0.00035811.4641
Donate206013862021-10-25 16:33:38885 days ago1635179618IN
0xea195300...7e4e2BAf3
0 MATIC0.0058546530
Donate205996842021-10-25 15:23:14885 days ago1635175394IN
0xea195300...7e4e2BAf3
0 MATIC0.0090318330
Donate205920542021-10-25 10:18:33885 days ago1635157113IN
0xea195300...7e4e2BAf3
0 MATIC0.0090318330
Donate205914832021-10-25 9:56:47886 days ago1635155807IN
0xea195300...7e4e2BAf3
0 MATIC0.0107678430
Donate205519822021-10-24 7:15:42887 days ago1635059742IN
0xea195300...7e4e2BAf3
0 MATIC0.0093127530
Donate205362892021-10-23 21:22:53887 days ago1635024173IN
0xea195300...7e4e2BAf3
0 MATIC0.0046217130
Donate205329152021-10-23 19:14:05887 days ago1635016445IN
0xea195300...7e4e2BAf3
0 MATIC0.0115903530
Donate205314012021-10-23 18:13:53887 days ago1635012833IN
0xea195300...7e4e2BAf3
0 MATIC0.0090318330
Donate205313572021-10-23 18:12:01887 days ago1635012721IN
0xea195300...7e4e2BAf3
0 MATIC0.008258130
View all transactions

Latest 25 internal transactions (View All)

Parent Txn Hash Block From To Value
209120492021-11-02 22:16:39877 days ago1635891399
0xea195300...7e4e2BAf3
5 MATIC
208171382021-10-31 11:14:37879 days ago1635678877
0xea195300...7e4e2BAf3
0.1 MATIC
207636132021-10-30 2:48:33881 days ago1635562113
0xea195300...7e4e2BAf3
15 MATIC
207187832021-10-28 22:34:16882 days ago1635460456
0xea195300...7e4e2BAf3
10 MATIC
207175872021-10-28 21:44:40882 days ago1635457480
0xea195300...7e4e2BAf3
2 MATIC
207174132021-10-28 21:38:40882 days ago1635457120
0xea195300...7e4e2BAf3
5 MATIC
207164222021-10-28 20:59:54882 days ago1635454794
0xea195300...7e4e2BAf3
6 MATIC
207162952021-10-28 20:55:32882 days ago1635454532
0xea195300...7e4e2BAf3
15 MATIC
206018482021-10-25 16:49:30885 days ago1635180570
0xea195300...7e4e2BAf3
160 MATIC
205109842021-10-23 4:44:37888 days ago1634964277
0xea195300...7e4e2BAf3
11.11 MATIC
204938262021-10-22 17:05:01888 days ago1634922301
0xea195300...7e4e2BAf3
2 MATIC
204870302021-10-22 12:19:44888 days ago1634905184
0xea195300...7e4e2BAf3
0.3 MATIC
204869512021-10-22 12:17:02888 days ago1634905022
0xea195300...7e4e2BAf3
0.4 MATIC
204868622021-10-22 12:14:00888 days ago1634904840
0xea195300...7e4e2BAf3
0.3 MATIC
204864952021-10-22 12:00:18888 days ago1634904018
0xea195300...7e4e2BAf3
0.1 MATIC
204854142021-10-22 11:13:23888 days ago1634901203
0xea195300...7e4e2BAf3
1 MATIC
204843332021-10-22 10:31:57888 days ago1634898717
0xea195300...7e4e2BAf3
22 MATIC
204697462021-10-22 0:41:49889 days ago1634863309
0xea195300...7e4e2BAf3
10 MATIC
204605682021-10-21 18:30:45889 days ago1634841045
0xea195300...7e4e2BAf3
90 MATIC
204603842021-10-21 18:23:23889 days ago1634840603
0xea195300...7e4e2BAf3
5 MATIC
204603052021-10-21 18:19:35889 days ago1634840375
0xea195300...7e4e2BAf3
2 MATIC
204601662021-10-21 18:14:49889 days ago1634840089
0xea195300...7e4e2BAf3
168 MATIC
204594942021-10-21 17:49:33889 days ago1634838573
0xea195300...7e4e2BAf3
170 MATIC
204278812021-10-20 21:16:54890 days ago1634764614
0xea195300...7e4e2BAf3
1 MATIC
201800202021-10-13 17:00:18897 days ago1634144418
0xea195300...7e4e2BAf3
0.003 MATIC
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GrantRoundManagerUniV2

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 25000 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 9 : GrantRoundManagerUniV2.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import {IUniswapV2Router02 as ISwapRouter} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "./GrantRegistry.sol";
import "./GrantRound.sol";

/**
 * @notice dGrants GrantRoundManager implementation that uses Uniswap V2 to swap a user's tokens to the donationToken
 * in the `donate` method
 * @dev This implementation is intended to be used on L2s or sidechains that don't have a Uniswap V3 deployment
 * and therefore swaps during donations must be done on a Uniswap V2 fork. Because we are less concerned about
 * gas costs on these networks, and because there are many different forks that may have slight differences, we
 * call to an external router instead of inheriting from a router.
 * @dev Current implementation is hardcoded for Polygon mainnet + SushiSwap
 */
contract GrantRoundManagerUniV2 {
  // --- Libraries ---
  using Address for address;
  using SafeERC20 for IERC20;
  using SafeMath for uint256;

  // --- Data ---
  /// @notice Address of a router conforming to the Uniswap V2 interface
  ISwapRouter public constant router = ISwapRouter(0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506);

  /// @notice WETH address
  IERC20 public constant WETH = IERC20(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270);

  /// @notice Address of the GrantRegistry
  GrantRegistry public immutable registry;

  /// @notice Address of the ERC20 token in which donations are made
  IERC20 public immutable donationToken;

  /// @dev Used for saving off swap output amounts for verifying input parameters
  mapping(IERC20 => uint256) internal swapOutputs;

  /// @dev Used for saving off contribution ratios for verifying input parameters
  mapping(IERC20 => uint256) internal donationRatios;

  /// @dev Scale factor on percentages when constructing `Donation` objects. One WAD represents 100%
  uint256 internal constant WAD = 1e18;

  /// --- Types ---
  /// @dev Defines the total `amountIn` of the first token in `path` that needs to be swapped to `donationToken`
  struct SwapSummary {
    uint256 amountIn;
    uint256 amountOutMin; // minimum amount to be returned after swap
    address[] path; // Use `path == [donationToken]` to indicate no swap is required and just transfer the tokens directly
  }

  /// @dev Donation inputs and Uniswap V3 swap inputs: https://docs.uniswap.org/protocol/guides/swaps/multihop-swaps
  struct Donation {
    uint96 grantId; // grant ID to which donation is being made
    IERC20 token; // address of the token to donate
    uint256 ratio; // ratio of `token` to donate, specified as numerator where WAD = 1e18 = 100%
    GrantRound[] rounds; // rounds against which the donation should be counted
  }

  // --- Events ---
  /// @notice Emitted when a new GrantRound contract is created
  event GrantRoundCreated(address grantRound);

  /// @notice Emitted when a donation has been made
  event GrantDonation(uint96 indexed grantId, IERC20 indexed tokenIn, uint256 donationAmount, GrantRound[] rounds);

  // --- Constructor ---
  constructor(GrantRegistry _registry, IERC20 _donationToken) {
    // Validation
    require(_registry.grantCount() >= 0, "GrantRoundManager: Invalid registry");
    require(_donationToken.totalSupply() > 0, "GrantRoundManager: Invalid token");

    // Set state
    registry = _registry;
    donationToken = _donationToken;
  }

  // --- Core methods ---
  /**
   * @notice Creates a new GrantRound
   * @param _owner Grant round owner that has permission to update the metadata pointer
   * @param _payoutAdmin Grant round administrator that has permission to payout the matching pool
   * @param _matchingToken Address for the token used to payout match amounts at the end of a round
   * @param _startTime Unix timestamp of the start of the round
   * @param _endTime Unix timestamp of the end of the round
   * @param _metaPtr URL pointing to the grant round metadata
   */
  function createGrantRound(
    address _owner,
    address _payoutAdmin,
    IERC20 _matchingToken,
    uint256 _startTime,
    uint256 _endTime,
    string memory _metaPtr
  ) external {
    require(_matchingToken.totalSupply() > 0, "GrantRoundManager: Invalid matching token");
    GrantRound _grantRound = new GrantRound(
      _owner,
      _payoutAdmin,
      registry,
      donationToken,
      _matchingToken,
      _startTime,
      _endTime,
      _metaPtr
    );

    emit GrantRoundCreated(address(_grantRound));
  }

  /**
   * @notice Performs swaps if necessary and donates funds as specified
   * @param _swaps Array of SwapSummary objects describing the swaps required
   * @param _deadline Unix timestamp after which a swap will revert, i.e. swap must be executed before this
   * @param _donations Array of donations to execute
   * @dev `_deadline` is not part of the `_swaps` array since all swaps can use the same `_deadline` to save some gas
   * @dev Caller must ensure the input tokens to the _swaps array are unique
   */
  function donate(
    SwapSummary[] calldata _swaps,
    uint256 _deadline,
    Donation[] calldata _donations
  ) external payable {
    // Main logic
    _validateDonations(_donations);
    _executeDonationSwaps(_swaps, _deadline);
    _transferDonations(_donations);

    // Clear storage for refunds (this is set in _executeDonationSwaps)
    for (uint256 i = 0; i < _swaps.length; i++) {
      IERC20 _tokenIn = IERC20(_swaps[i].path[0]);
      swapOutputs[_tokenIn] = 0;
      donationRatios[_tokenIn] = 0;
    }
    for (uint256 i = 0; i < _donations.length; i++) {
      donationRatios[_donations[i].token] = 0;
    }
  }

  /**
   * @dev Validates the inputs to a donation call are valid, and reverts if any requirements are violated
   * @param _donations Array of donations that will be executed
   */
  function _validateDonations(Donation[] calldata _donations) internal {
    // TODO consider moving this to the section where we already loop through donations in case that saves a lot of
    // gas. Leaving it here for now to improve readability

    for (uint256 i = 0; i < _donations.length; i++) {
      // Validate grant exists
      require(_donations[i].grantId < registry.grantCount(), "GrantRoundManager: Grant does not exist in registry");

      // Used later to validate ratios are correctly provided
      donationRatios[_donations[i].token] = donationRatios[_donations[i].token].add(_donations[i].ratio);

      // Validate round parameters
      GrantRound[] calldata _rounds = _donations[i].rounds;
      for (uint256 j = 0; j < _rounds.length; j++) {
        require(_rounds[j].isActive(), "GrantRoundManager: GrantRound is not active");
        require(_rounds[j].registry() == registry, "GrantRoundManager: Round-Registry mismatch");
        require(
          donationToken == _rounds[j].donationToken(),
          "GrantRoundManager: GrantRound's donation token does not match GrantRoundManager's donation token"
        );
      }
    }
  }

  /**
   * @dev Performs swaps if necessary
   * @param _swaps Array of SwapSummary objects describing the swaps required
   * @param _deadline Unix timestamp after which a swap will revert, i.e. swap must be executed before this
   */
  function _executeDonationSwaps(SwapSummary[] calldata _swaps, uint256 _deadline) internal {
    for (uint256 i = 0; i < _swaps.length; i++) {
      // Validate output token is donation token (this can be done after the `continue` to save gas, but leaving it
      // here for now to minimize diff against GrantRoundManager.sol)
      address[] calldata _path = _swaps[i].path;
      IERC20 _outputToken = IERC20(_path[_path.length - 1]);
      require(_outputToken == donationToken, "GrantRoundManager: Output token must match donation token");

      // Validate ratios sum to 100%
      IERC20 _tokenIn = IERC20(_path[0]);
      require(donationRatios[_tokenIn] == WAD, "GrantRoundManager: Ratios do not sum to 100%");
      require(swapOutputs[_tokenIn] == 0, "GrantRoundManager: Swap parameter has duplicate input tokens");

      // WETH token donations are not supported, and only one WETH swap per transaction allowed
      require(
        _tokenIn != WETH || (_tokenIn == WETH && msg.value == _swaps[i].amountIn && msg.value > 0),
        "GrantRoundManager: WETH token donation issue"
      );

      // Do nothing if the swap input token equals donationToken
      if (_tokenIn == donationToken) {
        swapOutputs[_tokenIn] = _swaps[i].amountIn;
        continue;
      }

      // Get current balance of donation token, used to track swap outputss
      uint256 _initBalance = donationToken.balanceOf(address(this));

      // Execute swap
      if (_tokenIn != WETH) {
        // Swapping a token
        _tokenIn.safeTransferFrom(msg.sender, address(this), _swaps[i].amountIn);
        if (_tokenIn.allowance(address(this), address(router)) == 0) {
          _tokenIn.safeApprove(address(router), type(uint256).max);
        }

        router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
          _swaps[i].amountIn,
          _swaps[i].amountOutMin,
          _path,
          address(this),
          _deadline
        );
      } else {
        // Swapping ETH
        router.swapExactETHForTokensSupportingFeeOnTransferTokens{value: msg.value}(
          _swaps[i].amountOutMin,
          _path,
          address(this),
          _deadline
        );
      }

      // Save off output amount for later
      swapOutputs[_tokenIn] = donationToken.balanceOf(address(this)).sub(_initBalance);
    }
  }

  /**
   * @dev Core donation logic that transfers funds to grants
   * @param _donations Array of donations to execute
   */
  function _transferDonations(Donation[] calldata _donations) internal {
    for (uint256 i = 0; i < _donations.length; i++) {
      // Get data for this donation
      GrantRound[] calldata _rounds = _donations[i].rounds;
      uint96 _grantId = _donations[i].grantId;
      IERC20 _tokenIn = _donations[i].token;
      uint256 _donationAmount = (swapOutputs[_tokenIn].mul(_donations[i].ratio)) / WAD;
      require(_donationAmount > 0, "GrantRoundManager: Donation amount must be greater than zero"); // verifies that swap and donation inputs are consistent

      // Execute transfer
      emit GrantDonation(_grantId, _tokenIn, _donationAmount, _rounds);
      address _payee = registry.getGrantPayee(_grantId);
      if (_tokenIn == donationToken) {
        _tokenIn.safeTransferFrom(msg.sender, _payee, _donationAmount); // transfer token directly from caller
      } else {
        donationToken.transfer(_payee, _donationAmount); // transfer swap output
      }
    }
  }
}

File 2 of 9 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 3 of 9 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 4 of 9 : IUniswapV2Router02.sol
pragma solidity >=0.6.2;

import './IUniswapV2Router01.sol';

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

File 5 of 9 : GrantRegistry.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.7.6;
pragma abicoder v2;

/**
 * @notice The Gitcoin GrantRegistry contract keeps track of all grants that have been created.
 * It is designed to be a singleton, i.e. there is only one instance of a GrantRegistry which
 * tracks all grants. It behaves as follows:
 *   - Anyone can create a grant by calling `createGrant`
 *   - A grant's `owner` can edit their grant using the `updateGrant` family of method
 *   - The `getAllGrants` and `getGrants` view methods are used to fetch grant data
 */
contract GrantRegistry {
  // --- Data ---
  /// @notice Number of grants stored in this registry
  uint96 public grantCount;

  /// @notice Grant object
  struct Grant {
    uint96 id; // grant ID, as uint96 to pack into same slot as owner (this implies a max of 2^96-1 = 7.9e28 grants)
    address owner; // grant owner (has permissions to modify grant information)
    address payee; // address that receives funds donated to this grant
    string metaPtr; // URL pointing to grant metadata (for off-chain use)
  }

  // TODO use an array instead with ID to index it? Which is better?
  // TODO Will array copy full array to memory in `getAllGrants`?
  /// @notice Mapping from Grant ID to grant data
  mapping(uint96 => Grant) public grants;

  // --- Events ---
  /// @notice Emitted when a new grant is created
  event GrantCreated(uint96 indexed id, address indexed owner, address indexed payee, string metaPtr);

  /// @notice Emitted when a grant's owner is changed
  event GrantUpdated(uint96 indexed id, address indexed owner, address indexed payee, string metaPtr);

  // --- Core methods ---
  /**
   * @notice Create a new grant in the registry
   * @param _owner Grant owner (has permissions to modify grant information)
   * @param _payee Address that receives funds donated to this grant
   * @param _metaPtr URL pointing to grant metadata (for off-chain use)
   */
  function createGrant(
    address _owner,
    address _payee,
    string calldata _metaPtr
  ) external {
    uint96 _id = grantCount;
    grants[_id] = Grant(_id, _owner, _payee, _metaPtr);
    emit GrantCreated(_id, _owner, _payee, _metaPtr);
    grantCount += 1;
  }

  /**
   * @notice Update the owner of a grant
   * @param _id ID of grant to update
   * @param _owner New owner address
   */
  function updateGrantOwner(uint96 _id, address _owner) external {
    Grant storage grant = grants[_id];
    require(msg.sender == grant.owner, "GrantRegistry: Not authorized");
    grant.owner = _owner;
    emit GrantUpdated(grant.id, grant.owner, grant.payee, grant.metaPtr);
  }

  /**
   * @notice Update the payee of a grant
   * @param _id ID of grant to update
   * @param _payee New payee address
   */
  function updateGrantPayee(uint96 _id, address _payee) external {
    Grant storage grant = grants[_id];
    require(msg.sender == grant.owner, "GrantRegistry: Not authorized");
    grant.payee = _payee;
    emit GrantUpdated(grant.id, grant.owner, grant.payee, grant.metaPtr);
  }

  /**
   * @notice Update the metadata pointer of a grant
   * @param _id ID of grant to update
   * @param _metaPtr New URL that points to grant metadata
   */
  function updateGrantMetaPtr(uint96 _id, string calldata _metaPtr) external {
    Grant storage grant = grants[_id];
    require(msg.sender == grant.owner, "GrantRegistry: Not authorized");
    grant.metaPtr = _metaPtr;
    emit GrantUpdated(grant.id, grant.owner, grant.payee, grant.metaPtr);
  }

  /**
   * @notice Update multiple fields of a grant at once
   * @dev To leave a field unchanged, you must pass in the same value as the current value
   * @param _id ID of grant to update
   * @param _owner New owner address
   * @param _payee New payee address
   * @param _metaPtr New URL that points to grant metadata
   */
  function updateGrant(
    uint96 _id,
    address _owner,
    address _payee,
    string calldata _metaPtr
  ) external {
    require(msg.sender == grants[_id].owner, "GrantRegistry: Not authorized");
    grants[_id] = Grant({id: _id, owner: _owner, payee: _payee, metaPtr: _metaPtr});
    emit GrantUpdated(_id, _owner, _payee, _metaPtr);
  }

  // --- View functions ---
  /**
   * @notice Returns an array of all grants and their on-chain data
   * @dev May run out of gas for large values `grantCount`, depending on the node's RpcGasLimit. In these cases,
   * `getGrants` can be used to fetch a subset of grants and aggregate the results of various calls off-chain
   */
  function getAllGrants() external view returns (Grant[] memory) {
    return getGrants(0, grantCount);
  }

  /**
   * @notice Returns a range of grants and their on-chain data
   * @param _startId Grant ID of first grant to return, inclusive, i.e. this grant ID is included in return data
   * @param _endId Grant ID of last grant to return, exclusive, i.e. this grant ID is NOT included in return data
   */
  function getGrants(uint96 _startId, uint96 _endId) public view returns (Grant[] memory) {
    require(_endId <= grantCount, "GrantRegistry: _endId must be <= grantCount");
    require(_startId <= _endId, "GrantRegistry: Invalid ID range");
    Grant[] memory grantList = new Grant[](_endId - _startId);
    for (uint96 i = _startId; i < _endId; i++) {
      grantList[i - _startId] = grants[i]; // use index of `i - _startId` so index starts at zero
    }
    return grantList;
  }

  /**
   * @notice Returns the address that will be used to pay out donations for a given grant
   * @dev The payee may be set to null address
   * @param _id Grant ID used to retrieve the payee address in the registry
   */
  function getGrantPayee(uint96 _id) public view returns (address) {
    require(_id < grantCount, "GrantRegistry: Grant does not exist");
    Grant storage grant = grants[_id];
    return grant.payee;
  }
}

File 6 of 9 : GrantRound.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.7.6;

import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./GrantRegistry.sol";

contract GrantRound {
  using SafeERC20 for IERC20;

  // --- Data ---
  /// @notice Unix timestamp of the start of the round
  uint256 public immutable startTime;

  /// @notice Unix timestamp of the end of the round
  uint256 public immutable endTime;

  /// @notice Grant round payout administrator
  address public immutable payoutAdmin;

  /// @notice Grant round metadata administrator
  address public immutable metadataAdmin;

  /// @notice GrantsRegistry
  GrantRegistry public immutable registry;

  /// @notice Token used for all contributions. Contributions in a different token are swapped to this token
  IERC20 public immutable donationToken;

  /// @notice Token used to payout match amounts at the end of a round
  IERC20 public immutable matchingToken;

  /// @notice URL pointing to grant round metadata (for off-chain use)
  string public metaPtr;

  /// @notice Set to true if grant round has ended and payouts have been released
  bool public hasPaidOut;

  // --- Events ---
  /// @notice Emitted when a grant round metadata pointer is updated
  event MetadataUpdated(string oldMetaPtr, string indexed newMetaPtr);

  // --- Core methods ---
  /**
   * @notice Instantiates a new grant round
   * @param _metadataAdmin The address with the role that has permission to update the metadata pointer
   * @param _payoutAdmin Grant round administrator that has permission to payout the matching pool
   * @param _registry Address that contains the grant metadata
   * @param _donationToken Address of the ERC20 token in which donations are made
   * @param _matchingToken Address of the ERC20 token for accepting matching pool contributions
   * @param _startTime Unix timestamp of the start of the round
   * @param _endTime Unix timestamp of the end of the round
   * @param _metaPtr URL pointing to the grant round metadata
   */
  constructor(
    address _metadataAdmin,
    address _payoutAdmin,
    GrantRegistry _registry,
    IERC20 _donationToken,
    IERC20 _matchingToken,
    uint256 _startTime,
    uint256 _endTime,
    string memory _metaPtr
  ) {
    require(_donationToken.totalSupply() > 0, "GrantRound: Invalid donation token");
    require(_matchingToken.totalSupply() > 0, "GrantRound: Invalid matching token");
    require(_startTime >= block.timestamp, "GrantRound: Start time has already passed");
    require(_endTime > _startTime, "GrantRound: End time must be after start time");

    metadataAdmin = _metadataAdmin;
    payoutAdmin = _payoutAdmin;
    hasPaidOut = false;
    registry = _registry;
    donationToken = _donationToken;
    matchingToken = _matchingToken;
    startTime = _startTime;
    endTime = _endTime;
    metaPtr = _metaPtr;
  }

  /**
   * @notice Before the round ends this method accepts matching pool funds
   * @param _amount The amount of matching token that will be sent to the contract for the matching pool
   */
  function addMatchingFunds(uint256 _amount) external {
    require(block.timestamp < endTime, "GrantRound: Method must be called before round has ended");
    matchingToken.safeTransferFrom(msg.sender, address(this), _amount);
  }

  /**
   * @notice When the round ends the payoutAdmin can send the remaining matching pool funds to a given address
   * @param _payoutAddress An address to receive the remaining matching pool funds in the contract
   */
  function payoutGrants(address _payoutAddress) external {
    require(block.timestamp >= endTime, "GrantRound: Method must be called after round has ended");
    require(msg.sender == payoutAdmin, "GrantRound: Only the payout administrator can call this method");
    uint256 balance = matchingToken.balanceOf(address(this));
    hasPaidOut = true;
    matchingToken.safeTransfer(_payoutAddress, balance);
  }

  /**
   * @notice Updates the metadata pointer to a new location
   * @param _newMetaPtr A string where the updated metadata is stored
   */
  function updateMetadataPtr(string calldata _newMetaPtr) external {
    require(msg.sender == metadataAdmin, "GrantRound: Action can be perfomed only by metadataAdmin");
    emit MetadataUpdated(metaPtr, _newMetaPtr);
    metaPtr = _newMetaPtr;
  }

  /**
   * @notice Returns true if the round is active, false otherwise
   */
  function isActive() public view returns (bool) {
    return block.timestamp >= startTime && block.timestamp < endTime;
  }
}

File 7 of 9 : IUniswapV2Router01.sol
pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

File 8 of 9 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 9 of 9 : SafeMath.sol
// SPDX-License-Identifier: MIT

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, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @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) {
        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, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * 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);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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;
    }
}

Settings
{
  "metadata": {
    "bytecodeHash": "none"
  },
  "optimizer": {
    "enabled": true,
    "runs": 25000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract GrantRegistry","name":"_registry","type":"address"},{"internalType":"contract IERC20","name":"_donationToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint96","name":"grantId","type":"uint96"},{"indexed":true,"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"donationAmount","type":"uint256"},{"indexed":false,"internalType":"contract GrantRound[]","name":"rounds","type":"address[]"}],"name":"GrantDonation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"grantRound","type":"address"}],"name":"GrantRoundCreated","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_payoutAdmin","type":"address"},{"internalType":"contract IERC20","name":"_matchingToken","type":"address"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"string","name":"_metaPtr","type":"string"}],"name":"createGrantRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"internalType":"struct GrantRoundManagerUniV2.SwapSummary[]","name":"_swaps","type":"tuple[]"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"components":[{"internalType":"uint96","name":"grantId","type":"uint96"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"ratio","type":"uint256"},{"internalType":"contract GrantRound[]","name":"rounds","type":"address[]"}],"internalType":"struct GrantRoundManagerUniV2.Donation[]","name":"_donations","type":"tuple[]"}],"name":"donate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"donationToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract GrantRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b50604051620040b2380380620040b2833981016040819052620000349162000194565b6000826001600160a01b031663cab426726040518163ffffffff1660e01b815260040160206040518083038186803b1580156200007057600080fd5b505afa15801562000085573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ab9190620001eb565b6001600160601b03161015620000de5760405162461bcd60e51b8152600401620000d5906200021b565b60405180910390fd5b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200011a57600080fd5b505afa1580156200012f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001559190620001d2565b11620001755760405162461bcd60e51b8152600401620000d5906200025e565b6001600160601b0319606092831b8116608052911b1660a052620002ac565b60008060408385031215620001a7578182fd5b8251620001b48162000293565b6020840151909250620001c78162000293565b809150509250929050565b600060208284031215620001e4578081fd5b5051919050565b600060208284031215620001fd578081fd5b81516001600160601b038116811462000214578182fd5b9392505050565b60208082526023908201527f4772616e74526f756e644d616e616765723a20496e76616c696420726567697360408201526274727960e81b606082015260800190565b6020808252818101527f4772616e74526f756e644d616e616765723a20496e76616c696420746f6b656e604082015260600190565b6001600160a01b0381168114620002a957600080fd5b50565b60805160601c60a05160601c613da0620003126000398061012b52806103bd52806109c05280610ada5280610d2a5280610e125280611197528061151552806115cf52508061014f528061039c528061048952806107d952806114865250613da06000f3fe6080604052600436106200006e5760003560e01c8063ad5c46481162000049578063ad5c464814620000d4578063f208ce2114620000ec578063f887ea401462000111576200006e565b80630df7215914620000735780637b10399914620000a3578063a3040a4914620000bb575b600080fd5b3480156200008057600080fd5b506200008b62000129565b6040516200009a919062002089565b60405180910390f35b348015620000b057600080fd5b506200008b6200014d565b620000d2620000cc36600462001f39565b62000171565b005b348015620000e157600080fd5b506200008b620002b7565b348015620000f957600080fd5b50620000d26200010b36600462001e2e565b620002cf565b3480156200011e57600080fd5b506200008b62000463565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6200017d82826200047b565b6200018a85858562000a49565b62000196828262001289565b60005b8481101562000238576000868683818110620001b157fe5b9050602002810190620001c591906200277d565b620001d5906040810190620026a2565b6000818110620001e157fe5b9050602002016020810190620001f8919062001df0565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020818152604080832083905560019182905282209190915591909101905062000199565b5060005b81811015620002af576000600160008585858181106200025857fe5b90506020028101906200026c91906200273f565b6200027f90604081019060200162001df0565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020556001016200023c565b505050505050565b730d500b1d8e8ef31e21c99d1db9a6444d3adf127081565b60008473ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200031857600080fd5b505afa1580156200032d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000353919062001fd9565b1162000396576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620023f2565b60405180910390fd5b600086867f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000088888888604051620003ee9062001d96565b62000401989796959493929190620020d1565b604051809103906000f0801580156200041e573d6000803e3d6000fd5b5090507f459686c7ee2ee35189a6d953a149e4d78986e8883f995534669f91d511816d0f8160405162000452919062002089565b60405180910390a150505050505050565b731b02da8cb0d097eb8d57a175b88c7d8b4799750681565b60005b8181101562000a44577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cab426726040518163ffffffff1660e01b815260040160206040518083038186803b158015620004ee57600080fd5b505afa15801562000503573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000529919062002011565b6bffffffffffffffffffffffff168383838181106200054457fe5b90506020028101906200055891906200273f565b6200056890602081019062001ff2565b6bffffffffffffffffffffffff1610620005b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620022db565b6200063f838383818110620005c157fe5b9050602002810190620005d591906200273f565b6040013560016000868686818110620005ea57fe5b9050602002810190620005fe91906200273f565b6200061190604081019060200162001df0565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549062001673565b600160008585858181106200065057fe5b90506020028101906200066491906200273f565b6200067790604081019060200162001df0565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550366000848484818110620006c557fe5b9050602002810190620006d991906200273f565b620006e99060608101906200270a565b9150915060005b8181101562000a38578282828181106200070657fe5b90506020020160208101906200071d919062001df0565b73ffffffffffffffffffffffffffffffffffffffff166322f3e2d46040518163ffffffff1660e01b815260040160206040518083038186803b1580156200076357600080fd5b505afa15801562000778573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200079e919062001fb7565b620007d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620021c4565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168383838181106200081b57fe5b905060200201602081019062000832919062001df0565b73ffffffffffffffffffffffffffffffffffffffff16637b1039996040518163ffffffff1660e01b815260040160206040518083038186803b1580156200087857600080fd5b505afa1580156200088d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008b3919062001e0f565b73ffffffffffffffffffffffffffffffffffffffff161462000903576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620024d3565b8282828181106200091057fe5b905060200201602081019062000927919062001df0565b73ffffffffffffffffffffffffffffffffffffffff16630df721596040518163ffffffff1660e01b815260040160206040518083038186803b1580156200096d57600080fd5b505afa15801562000982573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620009a8919062001e0f565b73ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161462000a2f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d906200244f565b600101620006f0565b5050506001016200047e565b505050565b60005b82811015620012835736600085858481811062000a6557fe5b905060200281019062000a7991906200277d565b62000a89906040810190620026a2565b9092509050600082827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811062000abf57fe5b905060200201602081019062000ad6919062001df0565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161462000b60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002221565b60008383600081811062000b7057fe5b905060200201602081019062000b87919062001df0565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902054909150670de0b6b3a76400001462000bf3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002395565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020541562000c53576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d906200227e565b73ffffffffffffffffffffffffffffffffffffffff8116730d500b1d8e8ef31e21c99d1db9a6444d3adf127014158062000cef575073ffffffffffffffffffffffffffffffffffffffff8116730d500b1d8e8ef31e21c99d1db9a6444d3adf127014801562000ce2575087878681811062000cca57fe5b905060200281019062000cde91906200277d565b3534145b801562000cef5750600034115b62000d28576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002530565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000dd25787878681811062000d8a57fe5b905060200281019062000d9e91906200277d565b73ffffffffffffffffffffffffffffffffffffffff909116600090815260208190526040902090359055506200127a915050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a082319062000e4990309060040162002089565b60206040518083038186803b15801562000e6257600080fd5b505afa15801562000e77573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e9d919062001fd9565b905073ffffffffffffffffffffffffffffffffffffffff8216730d500b1d8e8ef31e21c99d1db9a6444d3adf127014620010f55762000f1933308b8b8a81811062000ee457fe5b905060200281019062000ef891906200277d565b73ffffffffffffffffffffffffffffffffffffffff861692919035620016f1565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063dd62ed3e9062000f83903090731b02da8cb0d097eb8d57a175b88c7d8b4799750690600401620020aa565b60206040518083038186803b15801562000f9c57600080fd5b505afa15801562000fb1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000fd7919062001fd9565b62001033576200103373ffffffffffffffffffffffffffffffffffffffff8316731b02da8cb0d097eb8d57a175b88c7d8b479975067fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff62001788565b731b02da8cb0d097eb8d57a175b88c7d8b47997506635c11d7958a8a898181106200105a57fe5b90506020028101906200106e91906200277d565b358b8b8a8181106200107c57fe5b90506020028101906200109091906200277d565b602001358888308d6040518763ffffffff1660e01b8152600401620010bb969594939291906200263c565b600060405180830381600087803b158015620010d657600080fd5b505af1158015620010eb573d6000803e3d6000fd5b5050505062001190565b731b02da8cb0d097eb8d57a175b88c7d8b4799750663b6f9de95348b8b8a8181106200111d57fe5b90506020028101906200113191906200277d565b602001358888308d6040518763ffffffff1660e01b81526004016200115b9594939291906200258d565b6000604051808303818588803b1580156200117557600080fd5b505af11580156200118a573d6000803e3d6000fd5b50505050505b6200124b817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401620011f0919062002089565b60206040518083038186803b1580156200120957600080fd5b505afa1580156200121e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001244919062001fd9565b906200191e565b73ffffffffffffffffffffffffffffffffffffffff909216600090815260208190526040902091909155505050505b60010162000a4c565b50505050565b60005b8181101562000a4457366000848484818110620012a557fe5b9050602002810190620012b991906200273f565b620012c99060608101906200270a565b915091506000858585818110620012dc57fe5b9050602002810190620012f091906200273f565b6200130090602081019062001ff2565b905060008686868181106200131157fe5b90506020028101906200132591906200273f565b6200133890604081019060200162001df0565b90506000670de0b6b3a76400006200139b8989898181106200135657fe5b90506020028101906200136a91906200273f565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040908190205491013562001996565b81620013a357fe5b04905060008111620013e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002338565b8173ffffffffffffffffffffffffffffffffffffffff16836bffffffffffffffffffffffff167f086fa7b62893eaaf4ec9bc3800b35c58174698a18694d73140ed498594844a108388886040516200143e93929190620025d3565b60405180910390a36040517fe1f7b92f00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e1f7b92f90620014bd90879060040162002689565b60206040518083038186803b158015620014d657600080fd5b505afa158015620014eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001511919062001e0f565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141562001592576200158c73ffffffffffffffffffffffffffffffffffffffff8416338385620016f1565b62001660565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906200160890849086906004016200219e565b602060405180830381600087803b1580156200162357600080fd5b505af115801562001638573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200165e919062001fb7565b505b5050600190940193506200128c92505050565b600082820183811015620016e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526200128390859062001a0e565b801580620018385750604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200180857600080fd5b505afa1580156200181d573d6000803e3d6000fd5b505050506040513d60208110156200183457600080fd5b5051155b6200188f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018062003d5e6036913960400191505060405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905262000a4490849062001a0e565b6000828211156200199057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082620019a757506000620016eb565b82820282848281620019b557fe5b0414620016e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018062003d136021913960400191505060405180910390fd5b600062001a72826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1662001aec9092919063ffffffff16565b80519091501562000a445780806020019051602081101562001a9357600080fd5b505162000a44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018062003d34602a913960400191505060405180910390fd5b606062001afd848460008562001b07565b90505b9392505050565b60608247101562001b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018062003ced6026913960400191505060405180910390fd5b62001b6f8562001ccc565b62001bdb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831062001c4657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910162001c07565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811462001caa576040519150601f19603f3d011682016040523d82523d6000602084013e62001caf565b606091505b509150915062001cc182828662001cd2565b979650505050505050565b3b151590565b6060831562001ce357508162001b00565b82511562001cf45782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101562001d5a57818101518382015260200162001d40565b50505050905090810190601f16801562001d885780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6114fa80620027f383390190565b60008083601f84011262001db6578081fd5b50813567ffffffffffffffff81111562001dce578182fd5b602083019150836020808302850101111562001de957600080fd5b9250929050565b60006020828403121562001e02578081fd5b8135620016e881620027b1565b60006020828403121562001e21578081fd5b8151620016e881620027b1565b60008060008060008060c0878903121562001e47578182fd5b863562001e5481620027b1565b955060208781013562001e6781620027b1565b9550604088013562001e7981620027b1565b9450606088013593506080880135925060a088013567ffffffffffffffff8082111562001ea4578384fd5b818a0191508a601f83011262001eb8578384fd5b81358181111562001ec557fe5b604051847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116820101818110848211171562001f0157fe5b60405281815283820185018d101562001f18578586fd5b81858501868301378585838301015280955050505050509295509295509295565b60008060008060006060868803121562001f51578081fd5b853567ffffffffffffffff8082111562001f69578283fd5b62001f7789838a0162001da4565b909750955060208801359450604088013591508082111562001f97578283fd5b5062001fa68882890162001da4565b969995985093965092949392505050565b60006020828403121562001fc9578081fd5b81518015158114620016e8578182fd5b60006020828403121562001feb578081fd5b5051919050565b60006020828403121562002004578081fd5b8135620016e881620027d7565b60006020828403121562002023578081fd5b8151620016e881620027d7565b60008284526020808501945082825b858110156200207e5781356200205581620027b1565b73ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016200203f565b509495945050505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600061010073ffffffffffffffffffffffffffffffffffffffff808c1684526020818c1681860152818b166040860152818a16606086015281891660808601528760a08601528660c08601528260e0860152855191508183860152835b828110156200214d57868101820151868201850183015281016200212e565b8281111562002160578482858589010101525b50601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01693909301019091019998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6020808252602b908201527f4772616e74526f756e644d616e616765723a204772616e74526f756e6420697360408201527f206e6f7420616374697665000000000000000000000000000000000000000000606082015260800190565b60208082526039908201527f4772616e74526f756e644d616e616765723a204f757470757420746f6b656e2060408201527f6d757374206d6174636820646f6e6174696f6e20746f6b656e00000000000000606082015260800190565b6020808252603c908201527f4772616e74526f756e644d616e616765723a205377617020706172616d65746560408201527f7220686173206475706c696361746520696e70757420746f6b656e7300000000606082015260800190565b60208082526033908201527f4772616e74526f756e644d616e616765723a204772616e7420646f6573206e6f60408201527f7420657869737420696e20726567697374727900000000000000000000000000606082015260800190565b6020808252603c908201527f4772616e74526f756e644d616e616765723a20446f6e6174696f6e20616d6f7560408201527f6e74206d7573742062652067726561746572207468616e207a65726f00000000606082015260800190565b6020808252602c908201527f4772616e74526f756e644d616e616765723a20526174696f7320646f206e6f7460408201527f2073756d20746f20313030250000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f4772616e74526f756e644d616e616765723a20496e76616c6964206d6174636860408201527f696e6720746f6b656e0000000000000000000000000000000000000000000000606082015260800190565b602080825260609082018190527f4772616e74526f756e644d616e616765723a204772616e74526f756e6427732060408301527f646f6e6174696f6e20746f6b656e20646f6573206e6f74206d61746368204772908201527f616e74526f756e644d616e61676572277320646f6e6174696f6e20746f6b656e608082015260a00190565b6020808252602a908201527f4772616e74526f756e644d616e616765723a20526f756e642d5265676973747260408201527f79206d69736d6174636800000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4772616e74526f756e644d616e616765723a205745544820746f6b656e20646f60408201527f6e6174696f6e2069737375650000000000000000000000000000000000000000606082015260800190565b600086825260806020830152620025a960808301868862002030565b73ffffffffffffffffffffffffffffffffffffffff94909416604083015250606001529392505050565b83815260406020808301829052908201839052600090849060608401835b86811015620026305783356200260781620027b1565b73ffffffffffffffffffffffffffffffffffffffff1682529282019290820190600101620025f1565b50979650505050505050565b600087825286602083015260a060408301526200265e60a08301868862002030565b73ffffffffffffffffffffffffffffffffffffffff9490941660608301525060800152949350505050565b6bffffffffffffffffffffffff91909116815260200190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112620026d7578283fd5b83018035915067ffffffffffffffff821115620026f2578283fd5b602090810192508102360382131562001de957600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112620026d7578182fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811262002773578182fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811262002773578182fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620027d457600080fd5b50565b6bffffffffffffffffffffffff81168114620027d457600080fdfe6101606040523480156200001257600080fd5b50604051620014fa380380620014fa83398181016040526101008110156200003957600080fd5b815160208301516040808501516060860151608087015160a088015160c089015160e08a0180519651989a9799959894979396929591949391820192846401000000008211156200008957600080fd5b9083019060208201858111156200009f57600080fd5b8251640100000000811182820188101715620000ba57600080fd5b82525081516020918201929091019080838360005b83811015620000e9578181015183820152602001620000cf565b50505050905090810190601f168015620001175780820380516001836020036101000a031916815260200191505b506040525050506000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200015a57600080fd5b505afa1580156200016f573d6000803e3d6000fd5b505050506040513d60208110156200018657600080fd5b505111620001c65760405162461bcd60e51b8152600401808060200182810382526022815260200180620014ab6022913960400191505060405180910390fd5b6000846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200020257600080fd5b505afa15801562000217573d6000803e3d6000fd5b505050506040513d60208110156200022e57600080fd5b5051116200026e5760405162461bcd60e51b8152600401808060200182810382526022815260200180620014606022913960400191505060405180910390fd5b42831015620002af5760405162461bcd60e51b8152600401808060200182810382526029815260200180620014826029913960400191505060405180910390fd5b828211620002ef5760405162461bcd60e51b815260040180806020018281038252602d815260200180620014cd602d913960400191505060405180910390fd5b6001600160601b0319606089811b821660e05288811b821660c0526001805460ff1916905587811b82166101005286811b82166101205285901b1661014052608083905260a082905280516200034d9060009060208401906200035c565b50505050505050505062000408565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620003945760008555620003df565b82601f10620003af57805160ff1916838001178555620003df565b82800160010185558215620003df579182015b82811115620003df578251825591602001919060010190620003c2565b50620003ed929150620003f1565b5090565b5b80821115620003ed5760008155600101620003f2565b60805160a05160c05160601c60e05160601c6101005160601c6101205160601c6101405160601c610fc862000498600039806102e052806104fc52806105f352806106b05250806102bc5250806103cf52508061037e52806106f3525080610482528061090e525080610331528061035a52806103f3528061062052508061030652806103ab5250610fc86000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806378e979251161008c5780639c55813f116100665780639c55813f146101a85780639d1726b3146101c5578063d0e363cb14610235578063f477ac6c146102b2576100df565b806378e97925146101635780637b1039991461016b5780639aa233fd14610173576100df565b80633197cbb6116100bd5780633197cbb6146101395780633292bead146101535780634aec766a1461015b576100df565b80630df72159146100e4578063171154c81461011557806322f3e2d41461011d575b600080fd5b6100ec6102ba565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100ec6102de565b610125610302565b604080519115158252519081900360200190f35b610141610358565b60408051918252519081900360200190f35b6100ec61037c565b6101256103a0565b6101416103a9565b6100ec6103cd565b6101a66004803603602081101561018957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166103f1565b005b6101a6600480360360208110156101be57600080fd5b503561061e565b6101a6600480360360208110156101db57600080fd5b8101906020810181356401000000008111156101f657600080fd5b82018360208201111561020857600080fd5b8035906020019184600183028401116401000000008311171561022a57600080fd5b5090925090506106db565b61023d610860565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561027757818101518382015260200161025f565b50505050905090810190601f1680156102a45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100ec61090c565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000421015801561035357507f000000000000000000000000000000000000000000000000000000000000000042105b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015460ff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000042101561046a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526037815260200180610f856037913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146104f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603e815260200180610e87603e913960400191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561058157600080fd5b505afa158015610595573d6000803e3d6000fd5b505050506040513d60208110156105ab57600080fd5b5051600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681179055905061061a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168383610930565b5050565b7f00000000000000000000000000000000000000000000000000000000000000004210610696576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180610ec56038913960400191505060405180910390fd5b6106d873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846109bd565b50565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610769576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180610f236038913960400191505060405180910390fd5b8181604051808383808284376040805193909101839003832060208085526000805460027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010060018416150201909116049186018290529197507f30f5c4b652f95e2a697bda3258896c421eee4f29adce8fe38060f47f7aed91ad965090945083925090820190849080156108415780601f1061081657610100808354040283529160200191610841565b820191906000526020600020905b81548152906001019060200180831161082457829003601f168201915b50509250505060405180910390a261085b60008383610dc7565b505050565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156109045780601f106108d957610100808354040283529160200191610904565b820191906000526020600020905b8154815290600101906020018083116108e757829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261085b908490610a58565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610a52908590610a58565b50505050565b6000610aba826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610b309092919063ffffffff16565b80519091501561085b57808060200190516020811015610ad957600080fd5b505161085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610f5b602a913960400191505060405180910390fd5b6060610b3f8484600085610b49565b90505b9392505050565b606082471015610ba4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610efd6026913960400191505060405180910390fd5b610bad85610d03565b610c1857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610c8157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c44565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610ce3576040519150601f19603f3d011682016040523d82523d6000602084013e610ce8565b606091505b5091509150610cf8828286610d09565b979650505050505050565b3b151590565b60608315610d18575081610b42565b825115610d285782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d8c578181015183820152602001610d74565b50505050905090810190601f168015610db95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282610dfd5760008555610e61565b82601f10610e34578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555610e61565b82800160010185558215610e61579182015b82811115610e61578235825591602001919060010190610e46565b50610e6d929150610e71565b5090565b5b80821115610e6d5760008155600101610e7256fe4772616e74526f756e643a204f6e6c7920746865207061796f75742061646d696e6973747261746f722063616e2063616c6c2074686973206d6574686f644772616e74526f756e643a204d6574686f64206d7573742062652063616c6c6564206265666f726520726f756e642068617320656e646564416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4772616e74526f756e643a20416374696f6e2063616e20626520706572666f6d6564206f6e6c79206279206d6574616461746141646d696e5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644772616e74526f756e643a204d6574686f64206d7573742062652063616c6c656420616674657220726f756e642068617320656e646564a164736f6c6343000706000a4772616e74526f756e643a20496e76616c6964206d61746368696e6720746f6b656e4772616e74526f756e643a2053746172742074696d652068617320616c7265616479207061737365644772616e74526f756e643a20496e76616c696420646f6e6174696f6e20746f6b656e4772616e74526f756e643a20456e642074696d65206d7573742062652061667465722073746172742074696d65416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a164736f6c6343000706000a0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063

Deployed Bytecode

0x6080604052600436106200006e5760003560e01c8063ad5c46481162000049578063ad5c464814620000d4578063f208ce2114620000ec578063f887ea401462000111576200006e565b80630df7215914620000735780637b10399914620000a3578063a3040a4914620000bb575b600080fd5b3480156200008057600080fd5b506200008b62000129565b6040516200009a919062002089565b60405180910390f35b348015620000b057600080fd5b506200008b6200014d565b620000d2620000cc36600462001f39565b62000171565b005b348015620000e157600080fd5b506200008b620002b7565b348015620000f957600080fd5b50620000d26200010b36600462001e2e565b620002cf565b3480156200011e57600080fd5b506200008b62000463565b7f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06381565b7f0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c081565b6200017d82826200047b565b6200018a85858562000a49565b62000196828262001289565b60005b8481101562000238576000868683818110620001b157fe5b9050602002810190620001c591906200277d565b620001d5906040810190620026a2565b6000818110620001e157fe5b9050602002016020810190620001f8919062001df0565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020818152604080832083905560019182905282209190915591909101905062000199565b5060005b81811015620002af576000600160008585858181106200025857fe5b90506020028101906200026c91906200273f565b6200027f90604081019060200162001df0565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020556001016200023c565b505050505050565b730d500b1d8e8ef31e21c99d1db9a6444d3adf127081565b60008473ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200031857600080fd5b505afa1580156200032d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000353919062001fd9565b1162000396576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620023f2565b60405180910390fd5b600086867f0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c07f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06388888888604051620003ee9062001d96565b62000401989796959493929190620020d1565b604051809103906000f0801580156200041e573d6000803e3d6000fd5b5090507f459686c7ee2ee35189a6d953a149e4d78986e8883f995534669f91d511816d0f8160405162000452919062002089565b60405180910390a150505050505050565b731b02da8cb0d097eb8d57a175b88c7d8b4799750681565b60005b8181101562000a44577f0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c073ffffffffffffffffffffffffffffffffffffffff1663cab426726040518163ffffffff1660e01b815260040160206040518083038186803b158015620004ee57600080fd5b505afa15801562000503573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000529919062002011565b6bffffffffffffffffffffffff168383838181106200054457fe5b90506020028101906200055891906200273f565b6200056890602081019062001ff2565b6bffffffffffffffffffffffff1610620005b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620022db565b6200063f838383818110620005c157fe5b9050602002810190620005d591906200273f565b6040013560016000868686818110620005ea57fe5b9050602002810190620005fe91906200273f565b6200061190604081019060200162001df0565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549062001673565b600160008585858181106200065057fe5b90506020028101906200066491906200273f565b6200067790604081019060200162001df0565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550366000848484818110620006c557fe5b9050602002810190620006d991906200273f565b620006e99060608101906200270a565b9150915060005b8181101562000a38578282828181106200070657fe5b90506020020160208101906200071d919062001df0565b73ffffffffffffffffffffffffffffffffffffffff166322f3e2d46040518163ffffffff1660e01b815260040160206040518083038186803b1580156200076357600080fd5b505afa15801562000778573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200079e919062001fb7565b620007d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620021c4565b7f0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c073ffffffffffffffffffffffffffffffffffffffff168383838181106200081b57fe5b905060200201602081019062000832919062001df0565b73ffffffffffffffffffffffffffffffffffffffff16637b1039996040518163ffffffff1660e01b815260040160206040518083038186803b1580156200087857600080fd5b505afa1580156200088d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008b3919062001e0f565b73ffffffffffffffffffffffffffffffffffffffff161462000903576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d90620024d3565b8282828181106200091057fe5b905060200201602081019062000927919062001df0565b73ffffffffffffffffffffffffffffffffffffffff16630df721596040518163ffffffff1660e01b815260040160206040518083038186803b1580156200096d57600080fd5b505afa15801562000982573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620009a8919062001e0f565b73ffffffffffffffffffffffffffffffffffffffff167f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06373ffffffffffffffffffffffffffffffffffffffff161462000a2f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d906200244f565b600101620006f0565b5050506001016200047e565b505050565b60005b82811015620012835736600085858481811062000a6557fe5b905060200281019062000a7991906200277d565b62000a89906040810190620026a2565b9092509050600082827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811062000abf57fe5b905060200201602081019062000ad6919062001df0565b90507f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161462000b60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002221565b60008383600081811062000b7057fe5b905060200201602081019062000b87919062001df0565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902054909150670de0b6b3a76400001462000bf3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002395565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020541562000c53576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d906200227e565b73ffffffffffffffffffffffffffffffffffffffff8116730d500b1d8e8ef31e21c99d1db9a6444d3adf127014158062000cef575073ffffffffffffffffffffffffffffffffffffffff8116730d500b1d8e8ef31e21c99d1db9a6444d3adf127014801562000ce2575087878681811062000cca57fe5b905060200281019062000cde91906200277d565b3534145b801562000cef5750600034115b62000d28576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002530565b7f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000dd25787878681811062000d8a57fe5b905060200281019062000d9e91906200277d565b73ffffffffffffffffffffffffffffffffffffffff909116600090815260208190526040902090359055506200127a915050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06316906370a082319062000e4990309060040162002089565b60206040518083038186803b15801562000e6257600080fd5b505afa15801562000e77573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e9d919062001fd9565b905073ffffffffffffffffffffffffffffffffffffffff8216730d500b1d8e8ef31e21c99d1db9a6444d3adf127014620010f55762000f1933308b8b8a81811062000ee457fe5b905060200281019062000ef891906200277d565b73ffffffffffffffffffffffffffffffffffffffff861692919035620016f1565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063dd62ed3e9062000f83903090731b02da8cb0d097eb8d57a175b88c7d8b4799750690600401620020aa565b60206040518083038186803b15801562000f9c57600080fd5b505afa15801562000fb1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000fd7919062001fd9565b62001033576200103373ffffffffffffffffffffffffffffffffffffffff8316731b02da8cb0d097eb8d57a175b88c7d8b479975067fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff62001788565b731b02da8cb0d097eb8d57a175b88c7d8b47997506635c11d7958a8a898181106200105a57fe5b90506020028101906200106e91906200277d565b358b8b8a8181106200107c57fe5b90506020028101906200109091906200277d565b602001358888308d6040518763ffffffff1660e01b8152600401620010bb969594939291906200263c565b600060405180830381600087803b158015620010d657600080fd5b505af1158015620010eb573d6000803e3d6000fd5b5050505062001190565b731b02da8cb0d097eb8d57a175b88c7d8b4799750663b6f9de95348b8b8a8181106200111d57fe5b90506020028101906200113191906200277d565b602001358888308d6040518763ffffffff1660e01b81526004016200115b9594939291906200258d565b6000604051808303818588803b1580156200117557600080fd5b505af11580156200118a573d6000803e3d6000fd5b50505050505b6200124b817f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401620011f0919062002089565b60206040518083038186803b1580156200120957600080fd5b505afa1580156200121e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001244919062001fd9565b906200191e565b73ffffffffffffffffffffffffffffffffffffffff909216600090815260208190526040902091909155505050505b60010162000a4c565b50505050565b60005b8181101562000a4457366000848484818110620012a557fe5b9050602002810190620012b991906200273f565b620012c99060608101906200270a565b915091506000858585818110620012dc57fe5b9050602002810190620012f091906200273f565b6200130090602081019062001ff2565b905060008686868181106200131157fe5b90506020028101906200132591906200273f565b6200133890604081019060200162001df0565b90506000670de0b6b3a76400006200139b8989898181106200135657fe5b90506020028101906200136a91906200273f565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040908190205491013562001996565b81620013a357fe5b04905060008111620013e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038d9062002338565b8173ffffffffffffffffffffffffffffffffffffffff16836bffffffffffffffffffffffff167f086fa7b62893eaaf4ec9bc3800b35c58174698a18694d73140ed498594844a108388886040516200143e93929190620025d3565b60405180910390a36040517fe1f7b92f00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c0169063e1f7b92f90620014bd90879060040162002689565b60206040518083038186803b158015620014d657600080fd5b505afa158015620014eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001511919062001e0f565b90507f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a06373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141562001592576200158c73ffffffffffffffffffffffffffffffffffffffff8416338385620016f1565b62001660565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063169063a9059cbb906200160890849086906004016200219e565b602060405180830381600087803b1580156200162357600080fd5b505af115801562001638573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200165e919062001fb7565b505b5050600190940193506200128c92505050565b600082820183811015620016e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526200128390859062001a0e565b801580620018385750604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156200180857600080fd5b505afa1580156200181d573d6000803e3d6000fd5b505050506040513d60208110156200183457600080fd5b5051155b6200188f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018062003d5e6036913960400191505060405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905262000a4490849062001a0e565b6000828211156200199057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082620019a757506000620016eb565b82820282848281620019b557fe5b0414620016e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018062003d136021913960400191505060405180910390fd5b600062001a72826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1662001aec9092919063ffffffff16565b80519091501562000a445780806020019051602081101562001a9357600080fd5b505162000a44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018062003d34602a913960400191505060405180910390fd5b606062001afd848460008562001b07565b90505b9392505050565b60608247101562001b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018062003ced6026913960400191505060405180910390fd5b62001b6f8562001ccc565b62001bdb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831062001c4657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910162001c07565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811462001caa576040519150601f19603f3d011682016040523d82523d6000602084013e62001caf565b606091505b509150915062001cc182828662001cd2565b979650505050505050565b3b151590565b6060831562001ce357508162001b00565b82511562001cf45782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101562001d5a57818101518382015260200162001d40565b50505050905090810190601f16801562001d885780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6114fa80620027f383390190565b60008083601f84011262001db6578081fd5b50813567ffffffffffffffff81111562001dce578182fd5b602083019150836020808302850101111562001de957600080fd5b9250929050565b60006020828403121562001e02578081fd5b8135620016e881620027b1565b60006020828403121562001e21578081fd5b8151620016e881620027b1565b60008060008060008060c0878903121562001e47578182fd5b863562001e5481620027b1565b955060208781013562001e6781620027b1565b9550604088013562001e7981620027b1565b9450606088013593506080880135925060a088013567ffffffffffffffff8082111562001ea4578384fd5b818a0191508a601f83011262001eb8578384fd5b81358181111562001ec557fe5b604051847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116820101818110848211171562001f0157fe5b60405281815283820185018d101562001f18578586fd5b81858501868301378585838301015280955050505050509295509295509295565b60008060008060006060868803121562001f51578081fd5b853567ffffffffffffffff8082111562001f69578283fd5b62001f7789838a0162001da4565b909750955060208801359450604088013591508082111562001f97578283fd5b5062001fa68882890162001da4565b969995985093965092949392505050565b60006020828403121562001fc9578081fd5b81518015158114620016e8578182fd5b60006020828403121562001feb578081fd5b5051919050565b60006020828403121562002004578081fd5b8135620016e881620027d7565b60006020828403121562002023578081fd5b8151620016e881620027d7565b60008284526020808501945082825b858110156200207e5781356200205581620027b1565b73ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016200203f565b509495945050505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600061010073ffffffffffffffffffffffffffffffffffffffff808c1684526020818c1681860152818b166040860152818a16606086015281891660808601528760a08601528660c08601528260e0860152855191508183860152835b828110156200214d57868101820151868201850183015281016200212e565b8281111562002160578482858589010101525b50601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01693909301019091019998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6020808252602b908201527f4772616e74526f756e644d616e616765723a204772616e74526f756e6420697360408201527f206e6f7420616374697665000000000000000000000000000000000000000000606082015260800190565b60208082526039908201527f4772616e74526f756e644d616e616765723a204f757470757420746f6b656e2060408201527f6d757374206d6174636820646f6e6174696f6e20746f6b656e00000000000000606082015260800190565b6020808252603c908201527f4772616e74526f756e644d616e616765723a205377617020706172616d65746560408201527f7220686173206475706c696361746520696e70757420746f6b656e7300000000606082015260800190565b60208082526033908201527f4772616e74526f756e644d616e616765723a204772616e7420646f6573206e6f60408201527f7420657869737420696e20726567697374727900000000000000000000000000606082015260800190565b6020808252603c908201527f4772616e74526f756e644d616e616765723a20446f6e6174696f6e20616d6f7560408201527f6e74206d7573742062652067726561746572207468616e207a65726f00000000606082015260800190565b6020808252602c908201527f4772616e74526f756e644d616e616765723a20526174696f7320646f206e6f7460408201527f2073756d20746f20313030250000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f4772616e74526f756e644d616e616765723a20496e76616c6964206d6174636860408201527f696e6720746f6b656e0000000000000000000000000000000000000000000000606082015260800190565b602080825260609082018190527f4772616e74526f756e644d616e616765723a204772616e74526f756e6427732060408301527f646f6e6174696f6e20746f6b656e20646f6573206e6f74206d61746368204772908201527f616e74526f756e644d616e61676572277320646f6e6174696f6e20746f6b656e608082015260a00190565b6020808252602a908201527f4772616e74526f756e644d616e616765723a20526f756e642d5265676973747260408201527f79206d69736d6174636800000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4772616e74526f756e644d616e616765723a205745544820746f6b656e20646f60408201527f6e6174696f6e2069737375650000000000000000000000000000000000000000606082015260800190565b600086825260806020830152620025a960808301868862002030565b73ffffffffffffffffffffffffffffffffffffffff94909416604083015250606001529392505050565b83815260406020808301829052908201839052600090849060608401835b86811015620026305783356200260781620027b1565b73ffffffffffffffffffffffffffffffffffffffff1682529282019290820190600101620025f1565b50979650505050505050565b600087825286602083015260a060408301526200265e60a08301868862002030565b73ffffffffffffffffffffffffffffffffffffffff9490941660608301525060800152949350505050565b6bffffffffffffffffffffffff91909116815260200190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112620026d7578283fd5b83018035915067ffffffffffffffff821115620026f2578283fd5b602090810192508102360382131562001de957600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112620026d7578182fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811262002773578182fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811262002773578182fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620027d457600080fd5b50565b6bffffffffffffffffffffffff81168114620027d457600080fdfe6101606040523480156200001257600080fd5b50604051620014fa380380620014fa83398181016040526101008110156200003957600080fd5b815160208301516040808501516060860151608087015160a088015160c089015160e08a0180519651989a9799959894979396929591949391820192846401000000008211156200008957600080fd5b9083019060208201858111156200009f57600080fd5b8251640100000000811182820188101715620000ba57600080fd5b82525081516020918201929091019080838360005b83811015620000e9578181015183820152602001620000cf565b50505050905090810190601f168015620001175780820380516001836020036101000a031916815260200191505b506040525050506000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200015a57600080fd5b505afa1580156200016f573d6000803e3d6000fd5b505050506040513d60208110156200018657600080fd5b505111620001c65760405162461bcd60e51b8152600401808060200182810382526022815260200180620014ab6022913960400191505060405180910390fd5b6000846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200020257600080fd5b505afa15801562000217573d6000803e3d6000fd5b505050506040513d60208110156200022e57600080fd5b5051116200026e5760405162461bcd60e51b8152600401808060200182810382526022815260200180620014606022913960400191505060405180910390fd5b42831015620002af5760405162461bcd60e51b8152600401808060200182810382526029815260200180620014826029913960400191505060405180910390fd5b828211620002ef5760405162461bcd60e51b815260040180806020018281038252602d815260200180620014cd602d913960400191505060405180910390fd5b6001600160601b0319606089811b821660e05288811b821660c0526001805460ff1916905587811b82166101005286811b82166101205285901b1661014052608083905260a082905280516200034d9060009060208401906200035c565b50505050505050505062000408565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620003945760008555620003df565b82601f10620003af57805160ff1916838001178555620003df565b82800160010185558215620003df579182015b82811115620003df578251825591602001919060010190620003c2565b50620003ed929150620003f1565b5090565b5b80821115620003ed5760008155600101620003f2565b60805160a05160c05160601c60e05160601c6101005160601c6101205160601c6101405160601c610fc862000498600039806102e052806104fc52806105f352806106b05250806102bc5250806103cf52508061037e52806106f3525080610482528061090e525080610331528061035a52806103f3528061062052508061030652806103ab5250610fc86000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806378e979251161008c5780639c55813f116100665780639c55813f146101a85780639d1726b3146101c5578063d0e363cb14610235578063f477ac6c146102b2576100df565b806378e97925146101635780637b1039991461016b5780639aa233fd14610173576100df565b80633197cbb6116100bd5780633197cbb6146101395780633292bead146101535780634aec766a1461015b576100df565b80630df72159146100e4578063171154c81461011557806322f3e2d41461011d575b600080fd5b6100ec6102ba565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100ec6102de565b610125610302565b604080519115158252519081900360200190f35b610141610358565b60408051918252519081900360200190f35b6100ec61037c565b6101256103a0565b6101416103a9565b6100ec6103cd565b6101a66004803603602081101561018957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166103f1565b005b6101a6600480360360208110156101be57600080fd5b503561061e565b6101a6600480360360208110156101db57600080fd5b8101906020810181356401000000008111156101f657600080fd5b82018360208201111561020857600080fd5b8035906020019184600183028401116401000000008311171561022a57600080fd5b5090925090506106db565b61023d610860565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561027757818101518382015260200161025f565b50505050905090810190601f1680156102a45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100ec61090c565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f0000000000000000000000000000000000000000000000000000000000000000421015801561035357507f000000000000000000000000000000000000000000000000000000000000000042105b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015460ff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000042101561046a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526037815260200180610f856037913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146104f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603e815260200180610e87603e913960400191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561058157600080fd5b505afa158015610595573d6000803e3d6000fd5b505050506040513d60208110156105ab57600080fd5b5051600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681179055905061061a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168383610930565b5050565b7f00000000000000000000000000000000000000000000000000000000000000004210610696576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180610ec56038913960400191505060405180910390fd5b6106d873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846109bd565b50565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610769576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180610f236038913960400191505060405180910390fd5b8181604051808383808284376040805193909101839003832060208085526000805460027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010060018416150201909116049186018290529197507f30f5c4b652f95e2a697bda3258896c421eee4f29adce8fe38060f47f7aed91ad965090945083925090820190849080156108415780601f1061081657610100808354040283529160200191610841565b820191906000526020600020905b81548152906001019060200180831161082457829003601f168201915b50509250505060405180910390a261085b60008383610dc7565b505050565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156109045780601f106108d957610100808354040283529160200191610904565b820191906000526020600020905b8154815290600101906020018083116108e757829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261085b908490610a58565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610a52908590610a58565b50505050565b6000610aba826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610b309092919063ffffffff16565b80519091501561085b57808060200190516020811015610ad957600080fd5b505161085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610f5b602a913960400191505060405180910390fd5b6060610b3f8484600085610b49565b90505b9392505050565b606082471015610ba4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610efd6026913960400191505060405180910390fd5b610bad85610d03565b610c1857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610c8157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c44565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610ce3576040519150601f19603f3d011682016040523d82523d6000602084013e610ce8565b606091505b5091509150610cf8828286610d09565b979650505050505050565b3b151590565b60608315610d18575081610b42565b825115610d285782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d8c578181015183820152602001610d74565b50505050905090810190601f168015610db95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282610dfd5760008555610e61565b82601f10610e34578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555610e61565b82800160010185558215610e61579182015b82811115610e61578235825591602001919060010190610e46565b50610e6d929150610e71565b5090565b5b80821115610e6d5760008155600101610e7256fe4772616e74526f756e643a204f6e6c7920746865207061796f75742061646d696e6973747261746f722063616e2063616c6c2074686973206d6574686f644772616e74526f756e643a204d6574686f64206d7573742062652063616c6c6564206265666f726520726f756e642068617320656e646564416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4772616e74526f756e643a20416374696f6e2063616e20626520706572666f6d6564206f6e6c79206279206d6574616461746141646d696e5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644772616e74526f756e643a204d6574686f64206d7573742062652063616c6c656420616674657220726f756e642068617320656e646564a164736f6c6343000706000a4772616e74526f756e643a20496e76616c6964206d61746368696e6720746f6b656e4772616e74526f756e643a2053746172742074696d652068617320616c7265616479207061737365644772616e74526f756e643a20496e76616c696420646f6e6174696f6e20746f6b656e4772616e74526f756e643a20456e642074696d65206d7573742062652061667465722073746172742074696d65416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a164736f6c6343000706000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063

-----Decoded View---------------
Arg [0] : _registry (address): 0x7D6263A49B8C35fB149f0a536BDEFE8A22E841C0
Arg [1] : _donationToken (address): 0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000007d6263a49b8c35fb149f0a536bdefe8a22e841c0
Arg [1] : 0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063


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

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.