Goerli Testnet

Contract

0x5b62ccB7fdA139185374c8f36FAa388c20E1387F

Overview

ETH Balance

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Value
0x60e0604076279722022-09-20 14:58:00554 days ago1663685880IN
 Create: JBSingleTokenPaymentTerminalStore
0 ETH0.004888231.50000002

Latest 25 internal transactions (View All)

Advanced mode:
Parent Txn Hash Block From To Value
103908762024-01-17 19:54:0070 days ago1705521240
0x5b62ccB7...c20E1387F
0 ETH
103908762024-01-17 19:54:0070 days ago1705521240
0x5b62ccB7...c20E1387F
0 ETH
103798772024-01-15 18:19:4872 days ago1705342788
0x5b62ccB7...c20E1387F
0 ETH
103798772024-01-15 18:19:4872 days ago1705342788
0x5b62ccB7...c20E1387F
0 ETH
102682292023-12-25 10:46:0094 days ago1703501160
0x5b62ccB7...c20E1387F
0 ETH
102682292023-12-25 10:46:0094 days ago1703501160
0x5b62ccB7...c20E1387F
0 ETH
102682132023-12-25 10:40:4894 days ago1703500848
0x5b62ccB7...c20E1387F
0 ETH
102682132023-12-25 10:40:4894 days ago1703500848
0x5b62ccB7...c20E1387F
0 ETH
102659812023-12-25 0:17:2494 days ago1703463444
0x5b62ccB7...c20E1387F
0 ETH
102659812023-12-25 0:17:2494 days ago1703463444
0x5b62ccB7...c20E1387F
0 ETH
102618582023-12-24 5:30:4895 days ago1703395848
0x5b62ccB7...c20E1387F
0 ETH
102618582023-12-24 5:30:4895 days ago1703395848
0x5b62ccB7...c20E1387F
0 ETH
102353902023-12-19 4:13:24100 days ago1702959204
0x5b62ccB7...c20E1387F
0 ETH
102353902023-12-19 4:13:24100 days ago1702959204
0x5b62ccB7...c20E1387F
0 ETH
101658142023-12-06 4:49:24113 days ago1701838164
0x5b62ccB7...c20E1387F
0 ETH
101658142023-12-06 4:49:24113 days ago1701838164
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100592572023-11-17 12:12:24131 days ago1700223144
0x5b62ccB7...c20E1387F
0 ETH
100459532023-11-15 4:38:36134 days ago1700023116
0x5b62ccB7...c20E1387F
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
JBSingleTokenPaymentTerminalStore

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

File 5 of 47 : JBSingleTokenPaymentTerminalStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import '@paulrberg/contracts/math/PRBMath.sol';
import './interfaces/IJBController.sol';
import './interfaces/IJBFundingCycleDataSource.sol';
import './interfaces/IJBSingleTokenPaymentTerminalStore.sol';
import './libraries/JBConstants.sol';
import './libraries/JBCurrencies.sol';
import './libraries/JBFixedPointNumber.sol';
import './libraries/JBFundingCycleMetadataResolver.sol';
import './structs/JBPayDelegateAllocation.sol';
import './structs/JBPayParamsData.sol';

/**
  @notice
  Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.

  @dev
  Adheres to:
  IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.

  @dev
  Inherits from -
  ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.
*/
contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {
  // A library that parses the packed funding cycle metadata into a friendlier format.
  using JBFundingCycleMetadataResolver for JBFundingCycle;

  //*********************************************************************//
  // --------------------------- custom errors ------------------------- //
  //*********************************************************************//
  error INVALID_AMOUNT_TO_SEND_DELEGATE();
  error CURRENCY_MISMATCH();
  error DISTRIBUTION_AMOUNT_LIMIT_REACHED();
  error FUNDING_CYCLE_PAYMENT_PAUSED();
  error FUNDING_CYCLE_DISTRIBUTION_PAUSED();
  error FUNDING_CYCLE_REDEEM_PAUSED();
  error INADEQUATE_CONTROLLER_ALLOWANCE();
  error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();
  error INSUFFICIENT_TOKENS();
  error INVALID_FUNDING_CYCLE();
  error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();

  //*********************************************************************//
  // -------------------------- private constants ---------------------- //
  //*********************************************************************//

  /**
    @notice
    Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. 
  */
  uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;

  //*********************************************************************//
  // ---------------- public immutable stored properties --------------- //
  //*********************************************************************//

  /**
    @notice
    The directory of terminals and controllers for projects.
  */
  IJBDirectory public immutable override directory;

  /**
    @notice
    The contract storing all funding cycle configurations.
  */
  IJBFundingCycleStore public immutable override fundingCycleStore;

  /**
    @notice
    The contract that exposes price feeds.
  */
  IJBPrices public immutable override prices;

  //*********************************************************************//
  // --------------------- public stored properties -------------------- //
  //*********************************************************************//

  /**
    @notice
    The amount of tokens that each project has for each terminal, in terms of the terminal's token.

    @dev
    The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.

    _terminal The terminal to which the balance applies.
    _projectId The ID of the project to get the balance of.
  */
  mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;

  /**
    @notice
    The amount of funds that a project has distributed from its limit during the current funding cycle for each terminal, in terms of the distribution limit's currency.

    @dev
    Increases as projects use their preconfigured distribution limits.

    @dev
    The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.

    _terminal The terminal to which the used distribution limit applies.
    _projectId The ID of the project to get the used distribution limit of.
    _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.
  */
  mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))
    public
    override usedDistributionLimitOf;

  /**
    @notice
    The amount of funds that a project has used from its allowance during the current funding cycle configuration for each terminal, in terms of the overflow allowance's currency.

    @dev
    Increases as projects use their allowance.

    @dev
    The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.

    _terminal The terminal to which the overflow allowance applies.
    _projectId The ID of the project to get the used overflow allowance of.
    _configuration The configuration of the during which the allowance was used.
  */
  mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))
    public
    override usedOverflowAllowanceOf;

  //*********************************************************************//
  // ------------------------- external views -------------------------- //
  //*********************************************************************//

  /**
    @notice
    Gets the current overflowed amount in a terminal for a specified project.

    @dev
    The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.

    @param _terminal The terminal for which the overflow is being calculated.
    @param _projectId The ID of the project to get overflow for.

    @return The current amount of overflow that project has in the specified terminal.
  */
  function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)
    external
    view
    override
    returns (uint256)
  {
    // Return the overflow during the project's current funding cycle.
    return
      _overflowDuring(
        _terminal,
        _projectId,
        fundingCycleStore.currentOf(_projectId),
        _terminal.currency()
      );
  }

  /**
    @notice
    Gets the current overflowed amount for a specified project across all terminals.

    @param _projectId The ID of the project to get total overflow for.
    @param _decimals The number of decimals that the fixed point overflow should include.
    @param _currency The currency that the total overflow should be in terms of.

    @return The current total amount of overflow that project has across all terminals.
  */
  function currentTotalOverflowOf(
    uint256 _projectId,
    uint256 _decimals,
    uint256 _currency
  ) external view override returns (uint256) {
    return _currentTotalOverflowOf(_projectId, _decimals, _currency);
  }

  /**
    @notice
    The current amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens, using the total token supply and overflow in the ecosystem.

    @dev 
    If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.

    @dev
    The current reclaimable overflow is returned in terms of the specified terminal's currency.

    @dev
    The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.

    @param _terminal The terminal from which the reclaimable amount would come.
    @param _projectId The ID of the project to get the reclaimable overflow amount for.
    @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.
    @param _useTotalOverflow A flag indicating whether the overflow used in the calculation should be summed from all of the project's terminals. If false, overflow should be limited to the amount in the specified `_terminal`.

    @return The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.
  */
  function currentReclaimableOverflowOf(
    IJBSingleTokenPaymentTerminal _terminal,
    uint256 _projectId,
    uint256 _tokenCount,
    bool _useTotalOverflow
  ) external view override returns (uint256) {
    // Get a reference to the project's current funding cycle.
    JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);

    // Get the amount of current overflow.
    // Use the project's total overflow across all of its terminals if the flag species specifies so. Otherwise, use the overflow local to the specified terminal.
    uint256 _currentOverflow = _useTotalOverflow
      ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())
      : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());

    // If there's no overflow, there's no reclaimable overflow.
    if (_currentOverflow == 0) return 0;

    // Get the number of outstanding tokens the project has.
    uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))
      .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());

    // Can't redeem more tokens that is in the supply.
    if (_tokenCount > _totalSupply) return 0;

    // Return the reclaimable overflow amount.
    return
      _reclaimableOverflowDuring(
        _projectId,
        _fundingCycle,
        _tokenCount,
        _totalSupply,
        _currentOverflow
      );
  }

  /**
    @notice
    The current amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens, using the specified total token supply and overflow amounts.

    @dev 
    If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.

    @param _projectId The ID of the project to get the reclaimable overflow amount for.
    @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.
    @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.
    @param _overflow The amount of overflow to make the calculation with, as a fixed point number.

    @return The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.
  */
  function currentReclaimableOverflowOf(
    uint256 _projectId,
    uint256 _tokenCount,
    uint256 _totalSupply,
    uint256 _overflow
  ) external view override returns (uint256) {
    // If there's no overflow, there's no reclaimable overflow.
    if (_overflow == 0) return 0;

    // Can't redeem more tokens that is in the supply.
    if (_tokenCount > _totalSupply) return 0;

    // Get a reference to the project's current funding cycle.
    JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);

    // Return the reclaimable overflow amount.
    return
      _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);
  }

  //*********************************************************************//
  // -------------------------- constructor ---------------------------- //
  //*********************************************************************//

  /**
    @param _directory A contract storing directories of terminals and controllers for each project.
    @param _fundingCycleStore A contract storing all funding cycle configurations.
    @param _prices A contract that exposes price feeds.
  */
  constructor(
    IJBDirectory _directory,
    IJBFundingCycleStore _fundingCycleStore,
    IJBPrices _prices
  ) {
    directory = _directory;
    fundingCycleStore = _fundingCycleStore;
    prices = _prices;
  }

  //*********************************************************************//
  // ---------------------- external transactions ---------------------- //
  //*********************************************************************//

  /**
    @notice
    Records newly contributed tokens to a project.

    @dev
    Mints the project's tokens according to values provided by a configured data source. If no data source is configured, mints tokens proportional to the amount of the contribution.

    @dev
    The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.

    @param _payer The original address that sent the payment to the terminal.
    @param _amount The amount of tokens being paid. Includes the token being paid, the value, the number of decimals included, and the currency of the amount.
    @param _projectId The ID of the project being paid.
    @param _baseWeightCurrency The currency to base token issuance on.
    @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.
    @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.
    @param _metadata Bytes to send along to the data source, if one is provided.

    @return fundingCycle The project's funding cycle during which payment was made.
    @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.
    @return delegateAllocations The amount to send to delegates instead of adding to the local balance.
    @return memo A memo that should be passed along to the emitted event.
  */
  function recordPaymentFrom(
    address _payer,
    JBTokenAmount calldata _amount,
    uint256 _projectId,
    uint256 _baseWeightCurrency,
    address _beneficiary,
    string calldata _memo,
    bytes memory _metadata
  )
    external
    override
    nonReentrant
    returns (
      JBFundingCycle memory fundingCycle,
      uint256 tokenCount,
      JBPayDelegateAllocation[] memory delegateAllocations,
      string memory memo
    )
  {
    // Get a reference to the current funding cycle for the project.
    fundingCycle = fundingCycleStore.currentOf(_projectId);

    // The project must have a funding cycle configured.
    if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();

    // Must not be paused.
    if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();

    // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.
    uint256 _weight;

    // If the funding cycle has configured a data source, use it to derive a weight and memo.
    if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {
      // Create the params that'll be sent to the data source.
      JBPayParamsData memory _data = JBPayParamsData(
        IJBSingleTokenPaymentTerminal(msg.sender),
        _payer,
        _amount,
        _projectId,
        fundingCycle.configuration,
        _beneficiary,
        fundingCycle.weight,
        fundingCycle.reservedRate(),
        _memo,
        _metadata
      );
      (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())
        .payParams(_data);
    }
    // Otherwise use the funding cycle's weight
    else {
      _weight = fundingCycle.weight;
      memo = _memo;
    }

    // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.
    {
      // Keep a reference to the amount that should be added to the project's balance.
      uint256 _balanceDiff = _amount.value;

      // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.
      if (delegateAllocations.length != 0) {
        for (uint256 _i; _i < delegateAllocations.length; ) {
          // Get a reference to the amount to be delegated.
          uint256 _delegatedAmount = delegateAllocations[_i].amount;

          // Validate if non-zero.
          if (_delegatedAmount != 0) {
            // Can't delegate more than was paid.
            if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();

            // Decrement the total amount being added to the balance.
            _balanceDiff = _balanceDiff - _delegatedAmount;
          }

          unchecked {
            ++_i;
          }
        }
      }

      // If there's no amount being recorded, there's nothing left to do.
      if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);

      // Add the correct balance difference to the token balance of the project.
      if (_balanceDiff != 0)
        balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =
          balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +
          _balanceDiff;
    }

    // If there's no weight, token count must be 0 so there's nothing left to do.
    if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);

    // Get a reference to the number of decimals in the amount. (prevents stack too deep).
    uint256 _decimals = _amount.decimals;

    // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.
    // The weight is always a fixed point mumber with 18 decimals. To ensure this, the ratio should use the same number of decimals as the `_amount`.
    uint256 _weightRatio = _amount.currency == _baseWeightCurrency
      ? 10**_decimals
      : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);

    // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.
    tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);
  }

  /**
    @notice
    Records newly redeemed tokens of a project.

    @dev
    Redeems the project's tokens according to values provided by a configured data source. If no data source is configured, redeems tokens along a redemption bonding curve that is a function of the number of tokens being burned.

    @dev
    The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.

    @param _holder The account that is having its tokens redeemed.
    @param _projectId The ID of the project to which the tokens being redeemed belong.
    @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.
    @param _memo A memo to pass along to the emitted event.
    @param _metadata Bytes to send along to the data source, if one is provided.

    @return fundingCycle The funding cycle during which the redemption was made.
    @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.
    @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.
    @return memo A memo that should be passed along to the emitted event.
  */
  function recordRedemptionFor(
    address _holder,
    uint256 _projectId,
    uint256 _tokenCount,
    string memory _memo,
    bytes memory _metadata
  )
    external
    override
    nonReentrant
    returns (
      JBFundingCycle memory fundingCycle,
      uint256 reclaimAmount,
      JBRedemptionDelegateAllocation[] memory delegateAllocations,
      string memory memo
    )
  {
    // Get a reference to the project's current funding cycle.
    fundingCycle = fundingCycleStore.currentOf(_projectId);

    // The current funding cycle must not be paused.
    if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();

    // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.
    {
      // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.
      JBTokenAmount memory _reclaimedTokenAmount;
      uint256 _currentOverflow;
      uint256 _totalSupply;

      // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.
      {
        // Get a reference to the terminal's tokens.
        address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();

        // Get a reference to the terminal's decimals.
        uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();

        // Get areference to the terminal's currency.
        uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();

        // Get the amount of current overflow.
        // Use the local overflow if the funding cycle specifies that it should be used. Otherwise, use the project's total overflow across all of its terminals.
        _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()
          ? _currentTotalOverflowOf(_projectId, _decimals, _currency)
          : _overflowDuring(
            IJBSingleTokenPaymentTerminal(msg.sender),
            _projectId,
            fundingCycle,
            _currency
          );

        // Get the number of outstanding tokens the project has.
        _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(
          _projectId,
          fundingCycle.reservedRate()
        );

        // Can't redeem more tokens that is in the supply.
        if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();

        if (_currentOverflow != 0)
          // Calculate reclaim amount using the current overflow amount.
          reclaimAmount = _reclaimableOverflowDuring(
            _projectId,
            fundingCycle,
            _tokenCount,
            _totalSupply,
            _currentOverflow
          );

        _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);
      }

      // If the funding cycle has configured a data source, use it to derive a claim amount and memo.
      if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {
        // Yet another scoped section prevents stack too deep. `_state`  only used within scope.
        {
          // Get a reference to the ballot state.
          JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);

          // Create the params that'll be sent to the data source.
          JBRedeemParamsData memory _data = JBRedeemParamsData(
            IJBSingleTokenPaymentTerminal(msg.sender),
            _holder,
            _projectId,
            fundingCycle.configuration,
            _tokenCount,
            _totalSupply,
            _currentOverflow,
            _reclaimedTokenAmount,
            fundingCycle.useTotalOverflowForRedemptions(),
            _state == JBBallotState.Active
              ? fundingCycle.ballotRedemptionRate()
              : fundingCycle.redemptionRate(),
            _memo,
            _metadata
          );
          (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(
            fundingCycle.dataSource()
          ).redeemParams(_data);
        }
      } else {
        memo = _memo;
      }
    }

    // Keep a reference to the amount that should be subtracted from the project's balance.
    uint256 _balanceDiff = reclaimAmount;

    if (delegateAllocations.length != 0) {
      // Validate all delegated amounts.
      for (uint256 _i; _i < delegateAllocations.length; ) {
        // Get a reference to the amount to be delegated.
        uint256 _delegatedAmount = delegateAllocations[_i].amount;

        // Validate if non-zero.
        if (_delegatedAmount != 0)
          // Increment the total amount being subtracted from the balance.
          _balanceDiff = _balanceDiff + _delegatedAmount;

        unchecked {
          ++_i;
        }
      }
    }

    // The amount being reclaimed must be within the project's balance.
    if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])
      revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();

    // Remove the reclaimed funds from the project's balance.
    if (_balanceDiff != 0) {
      unchecked {
        balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =
          balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -
          _balanceDiff;
      }
    }
  }

  /**
    @notice
    Records newly distributed funds for a project.

    @dev
    The msg.sender must be an IJBSingleTokenPaymentTerminal. 

    @param _projectId The ID of the project that is having funds distributed.
    @param _amount The amount to use from the distribution limit, as a fixed point number.
    @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.

    @return fundingCycle The funding cycle during which the distribution was made.
    @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.
  */
  function recordDistributionFor(
    uint256 _projectId,
    uint256 _amount,
    uint256 _currency
  )
    external
    override
    nonReentrant
    returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)
  {
    // Get a reference to the project's current funding cycle.
    fundingCycle = fundingCycleStore.currentOf(_projectId);

    // The funding cycle must not be configured to have distributions paused.
    if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();

    // The new total amount that has been distributed during this funding cycle.
    uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[
      IJBSingleTokenPaymentTerminal(msg.sender)
    ][_projectId][fundingCycle.number] + _amount;

    // Amount must be within what is still distributable.
    (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(
      directory.controllerOf(_projectId)
    ).distributionLimitOf(
        _projectId,
        fundingCycle.configuration,
        IJBSingleTokenPaymentTerminal(msg.sender),
        IJBSingleTokenPaymentTerminal(msg.sender).token()
      );

    // Make sure the new used amount is within the distribution limit.
    if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)
      revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();

    // Make sure the currencies match.
    if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();

    // Get a reference to the terminal's currency.
    uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();

    // Convert the amount to the balance's currency.
    distributedAmount = (_currency == _balanceCurrency)
      ? _amount
      : PRBMath.mulDiv(
        _amount,
        10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.
        prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)
      );

    // The amount being distributed must be available.
    if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])
      revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();

    // Store the new amount.
    usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][
      fundingCycle.number
    ] = _newUsedDistributionLimitOf;

    // Removed the distributed funds from the project's token balance.
    unchecked {
      balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =
        balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -
        distributedAmount;
    }
  }

  /**
    @notice
    Records newly used allowance funds of a project.

    @dev
    The msg.sender must be an IJBSingleTokenPaymentTerminal. 

    @param _projectId The ID of the project to use the allowance of.
    @param _amount The amount to use from the allowance, as a fixed point number. 
    @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.

    @return fundingCycle The funding cycle during which the overflow allowance is being used.
    @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.
  */
  function recordUsedAllowanceOf(
    uint256 _projectId,
    uint256 _amount,
    uint256 _currency
  )
    external
    override
    nonReentrant
    returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)
  {
    // Get a reference to the project's current funding cycle.
    fundingCycle = fundingCycleStore.currentOf(_projectId);

    // Get a reference to the new used overflow allowance for this funding cycle configuration.
    uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[
      IJBSingleTokenPaymentTerminal(msg.sender)
    ][_projectId][fundingCycle.configuration] + _amount;

    // There must be sufficient allowance available.
    (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(
      directory.controllerOf(_projectId)
    ).overflowAllowanceOf(
        _projectId,
        fundingCycle.configuration,
        IJBSingleTokenPaymentTerminal(msg.sender),
        IJBSingleTokenPaymentTerminal(msg.sender).token()
      );

    // Make sure the new used amount is within the allowance.
    if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)
      revert INADEQUATE_CONTROLLER_ALLOWANCE();

    // Make sure the currencies match.
    if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();

    // Get a reference to the terminal's currency.
    uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();

    // Convert the amount to this store's terminal's token.
    usedAmount = (_currency == _balanceCurrency)
      ? _amount
      : PRBMath.mulDiv(
        _amount,
        10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.
        prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)
      );

    // The amount being distributed must be available in the overflow.
    if (
      usedAmount >
      _overflowDuring(
        IJBSingleTokenPaymentTerminal(msg.sender),
        _projectId,
        fundingCycle,
        _balanceCurrency
      )
    ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();

    // Store the incremented value.
    usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][
      fundingCycle.configuration
    ] = _newUsedOverflowAllowanceOf;

    // Update the project's balance.
    balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =
      balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -
      usedAmount;
  }

  /**
    @notice
    Records newly added funds for the project.

    @dev
    The msg.sender must be an IJBSingleTokenPaymentTerminal. 

    @param _projectId The ID of the project to which the funds being added belong.
    @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.
  */
  function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {
    // Increment the balance.
    balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =
      balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +
      _amount;
  }

  /**
    @notice
    Records the migration of funds from this store.

    @dev
    The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.

    @param _projectId The ID of the project being migrated.

    @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.
  */
  function recordMigration(uint256 _projectId)
    external
    override
    nonReentrant
    returns (uint256 balance)
  {
    // Get a reference to the project's current funding cycle.
    JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);

    // Migration must be allowed.
    if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();

    // Return the current balance.
    balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];

    // Set the balance to 0.
    balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;
  }

  //*********************************************************************//
  // --------------------- private helper functions -------------------- //
  //*********************************************************************//

  /**
    @notice
    The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.

    @dev 
    If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.

    @param _projectId The ID of the project to get the reclaimable overflow amount for.
    @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.
    @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.
    @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.
    @param _overflow The amount of overflow to make the calculation with.

    @return The amount of overflowed tokens that can be reclaimed.
  */
  function _reclaimableOverflowDuring(
    uint256 _projectId,
    JBFundingCycle memory _fundingCycle,
    uint256 _tokenCount,
    uint256 _totalSupply,
    uint256 _overflow
  ) private view returns (uint256) {
    // If the amount being redeemed is the total supply, return the rest of the overflow.
    if (_tokenCount == _totalSupply) return _overflow;

    // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.
    uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==
      JBBallotState.Active
      ? _fundingCycle.ballotRedemptionRate()
      : _fundingCycle.redemptionRate();

    // If the redemption rate is 0, nothing is claimable.
    if (_redemptionRate == 0) return 0;

    // Get a reference to the linear proportion.
    uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);

    // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.
    if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;

    return
      PRBMath.mulDiv(
        _base,
        _redemptionRate +
          PRBMath.mulDiv(
            _tokenCount,
            JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,
            _totalSupply
          ),
        JBConstants.MAX_REDEMPTION_RATE
      );
  }

  /**
    @notice
    Gets the amount that is overflowing when measured from the specified funding cycle.

    @dev
    This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.

    @param _terminal The terminal for which the overflow is being calculated.
    @param _projectId The ID of the project to get overflow for.
    @param _fundingCycle The ID of the funding cycle to base the overflow on.
    @param _balanceCurrency The currency that the stored balance is expected to be in terms of.

    @return overflow The overflow of funds, as a fixed point number with 18 decimals.
  */
  function _overflowDuring(
    IJBSingleTokenPaymentTerminal _terminal,
    uint256 _projectId,
    JBFundingCycle memory _fundingCycle,
    uint256 _balanceCurrency
  ) private view returns (uint256) {
    // Get the current balance of the project.
    uint256 _balanceOf = balanceOf[_terminal][_projectId];

    // If there's no balance, there's no overflow.
    if (_balanceOf == 0) return 0;

    // Get a reference to the distribution limit during the funding cycle.
    (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(
      directory.controllerOf(_projectId)
    ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());

    // Get a reference to the amount still distributable during the funding cycle.
    uint256 _distributionLimitRemaining = _distributionLimit -
      usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];

    // Convert the _distributionRemaining to be in terms of the provided currency.
    if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)
      _distributionLimitRemaining = PRBMath.mulDiv(
        _distributionLimitRemaining,
        10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.
        prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)
      );

    // Overflow is the balance of this project minus the amount that can still be distributed.
    unchecked {
      return
        _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;
    }
  }

  /**
    @notice
    Gets the amount that is currently overflowing across all of a project's terminals. 

    @dev
    This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.

    @param _projectId The ID of the project to get the total overflow for.
    @param _decimals The number of decimals that the fixed point overflow should include.
    @param _currency The currency that the overflow should be in terms of.

    @return overflow The total overflow of a project's funds.
  */
  function _currentTotalOverflowOf(
    uint256 _projectId,
    uint256 _decimals,
    uint256 _currency
  ) private view returns (uint256) {
    // Get a reference to the project's terminals.
    IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);

    // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.
    uint256 _ethOverflow;

    // Add the current ETH overflow for each terminal.
    for (uint256 _i; _i < _terminals.length; ) {
      _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);
      unchecked {
        ++_i;
      }
    }

    // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.
    uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH
      ? _ethOverflow
      : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));

    // Adjust the decimals of the fixed point number if needed to match the target decimals.
    return
      (_decimals == 18)
        ? _totalOverflow18Decimal
        : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);
  }
}

File 2 of 47 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

        _;

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

File 3 of 47 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

File 4 of 47 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 5 of 47 : PRBMath.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;

import "prb-math/contracts/PRBMath.sol";

File 6 of 47 : JBBallotState.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

enum JBBallotState {
  Active,
  Approved,
  Failed
}

File 7 of 47 : IJBController.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import './../structs/JBFundAccessConstraints.sol';
import './../structs/JBFundingCycleData.sol';
import './../structs/JBFundingCycleMetadata.sol';
import './../structs/JBGroupedSplits.sol';
import './../structs/JBProjectMetadata.sol';
import './IJBDirectory.sol';
import './IJBFundingCycleStore.sol';
import './IJBMigratable.sol';
import './IJBPaymentTerminal.sol';
import './IJBSplitsStore.sol';
import './IJBTokenStore.sol';

interface IJBController is IERC165 {
  event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);

  event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);

  event ReconfigureFundingCycles(
    uint256 configuration,
    uint256 projectId,
    string memo,
    address caller
  );

  event SetFundAccessConstraints(
    uint256 indexed fundingCycleConfiguration,
    uint256 indexed fundingCycleNumber,
    uint256 indexed projectId,
    JBFundAccessConstraints constraints,
    address caller
  );

  event DistributeReservedTokens(
    uint256 indexed fundingCycleConfiguration,
    uint256 indexed fundingCycleNumber,
    uint256 indexed projectId,
    address beneficiary,
    uint256 tokenCount,
    uint256 beneficiaryTokenCount,
    string memo,
    address caller
  );

  event DistributeToReservedTokenSplit(
    uint256 indexed projectId,
    uint256 indexed domain,
    uint256 indexed group,
    JBSplit split,
    uint256 tokenCount,
    address caller
  );

  event MintTokens(
    address indexed beneficiary,
    uint256 indexed projectId,
    uint256 tokenCount,
    uint256 beneficiaryTokenCount,
    string memo,
    uint256 reservedRate,
    address caller
  );

  event BurnTokens(
    address indexed holder,
    uint256 indexed projectId,
    uint256 tokenCount,
    string memo,
    address caller
  );

  event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);

  event PrepMigration(uint256 indexed projectId, address from, address caller);

  function projects() external view returns (IJBProjects);

  function fundingCycleStore() external view returns (IJBFundingCycleStore);

  function tokenStore() external view returns (IJBTokenStore);

  function splitsStore() external view returns (IJBSplitsStore);

  function directory() external view returns (IJBDirectory);

  function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)
    external
    view
    returns (uint256);

  function distributionLimitOf(
    uint256 _projectId,
    uint256 _configuration,
    IJBPaymentTerminal _terminal,
    address _token
  ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);

  function overflowAllowanceOf(
    uint256 _projectId,
    uint256 _configuration,
    IJBPaymentTerminal _terminal,
    address _token
  ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);

  function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)
    external
    view
    returns (uint256);

  function getFundingCycleOf(uint256 _projectId, uint256 _configuration)
    external
    view
    returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);

  function latestConfiguredFundingCycleOf(uint256 _projectId)
    external
    view
    returns (
      JBFundingCycle memory,
      JBFundingCycleMetadata memory metadata,
      JBBallotState
    );

  function currentFundingCycleOf(uint256 _projectId)
    external
    view
    returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);

  function queuedFundingCycleOf(uint256 _projectId)
    external
    view
    returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);

  function launchProjectFor(
    address _owner,
    JBProjectMetadata calldata _projectMetadata,
    JBFundingCycleData calldata _data,
    JBFundingCycleMetadata calldata _metadata,
    uint256 _mustStartAtOrAfter,
    JBGroupedSplits[] memory _groupedSplits,
    JBFundAccessConstraints[] memory _fundAccessConstraints,
    IJBPaymentTerminal[] memory _terminals,
    string calldata _memo
  ) external returns (uint256 projectId);

  function launchFundingCyclesFor(
    uint256 _projectId,
    JBFundingCycleData calldata _data,
    JBFundingCycleMetadata calldata _metadata,
    uint256 _mustStartAtOrAfter,
    JBGroupedSplits[] memory _groupedSplits,
    JBFundAccessConstraints[] memory _fundAccessConstraints,
    IJBPaymentTerminal[] memory _terminals,
    string calldata _memo
  ) external returns (uint256 configuration);

  function reconfigureFundingCyclesOf(
    uint256 _projectId,
    JBFundingCycleData calldata _data,
    JBFundingCycleMetadata calldata _metadata,
    uint256 _mustStartAtOrAfter,
    JBGroupedSplits[] memory _groupedSplits,
    JBFundAccessConstraints[] memory _fundAccessConstraints,
    string calldata _memo
  ) external returns (uint256);

  function mintTokensOf(
    uint256 _projectId,
    uint256 _tokenCount,
    address _beneficiary,
    string calldata _memo,
    bool _preferClaimedTokens,
    bool _useReservedRate
  ) external returns (uint256 beneficiaryTokenCount);

  function burnTokensOf(
    address _holder,
    uint256 _projectId,
    uint256 _tokenCount,
    string calldata _memo,
    bool _preferClaimedTokens
  ) external;

  function distributeReservedTokensOf(uint256 _projectId, string memory _memo)
    external
    returns (uint256);

  function migrate(uint256 _projectId, IJBMigratable _to) external;
}

File 8 of 47 : IJBDirectory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './IJBFundingCycleStore.sol';
import './IJBPaymentTerminal.sol';
import './IJBProjects.sol';

interface IJBDirectory {
  event SetController(uint256 indexed projectId, address indexed controller, address caller);

  event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);

  event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);

  event SetPrimaryTerminal(
    uint256 indexed projectId,
    address indexed token,
    IJBPaymentTerminal indexed terminal,
    address caller
  );

  event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);

  function projects() external view returns (IJBProjects);

  function fundingCycleStore() external view returns (IJBFundingCycleStore);

  function controllerOf(uint256 _projectId) external view returns (address);

  function isAllowedToSetFirstController(address _address) external view returns (bool);

  function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);

  function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)
    external
    view
    returns (bool);

  function primaryTerminalOf(uint256 _projectId, address _token)
    external
    view
    returns (IJBPaymentTerminal);

  function setControllerOf(uint256 _projectId, address _controller) external;

  function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;

  function setPrimaryTerminalOf(
    uint256 _projectId,
    address _token,
    IJBPaymentTerminal _terminal
  ) external;

  function setIsAllowedToSetFirstController(address _address, bool _flag) external;
}

File 9 of 47 : IJBFundingCycleBallot.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import './../enums/JBBallotState.sol';

interface IJBFundingCycleBallot is IERC165 {
  function duration() external view returns (uint256);

  function stateOf(
    uint256 _projectId,
    uint256 _configuration,
    uint256 _start
  ) external view returns (JBBallotState);
}

File 10 of 47 : IJBFundingCycleDataSource.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import './../structs/JBPayDelegateAllocation.sol';
import './../structs/JBPayParamsData.sol';
import './../structs/JBRedeemParamsData.sol';
import './../structs/JBRedemptionDelegateAllocation.sol';

/**
  @title
  Datasource

  @notice
  The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use 
  a custom weight, a custom memo and/or a pay/redeem delegate

  @dev
  Adheres to:
  IERC165 for adequate interface integration
*/
interface IJBFundingCycleDataSource is IERC165 {
  /**
    @notice
    The datasource implementation for JBPaymentTerminal.pay(..)

    @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:
                  IJBPaymentTerminal terminal;
                  address payer;
                  JBTokenAmount amount;
                  uint256 projectId;
                  uint256 currentFundingCycleConfiguration;
                  address beneficiary;
                  uint256 weight;
                  uint256 reservedRate;
                  string memo;
                  bytes metadata;

    @return weight the weight to use to override the funding cycle weight
    @return memo the memo to override the pay(..) memo
    @return delegateAllocations The amount to send to delegates instead of adding to the local balance.
  */
  function payParams(JBPayParamsData calldata _data)
    external
    returns (
      uint256 weight,
      string memory memo,
      JBPayDelegateAllocation[] memory delegateAllocations
    );

  /**
    @notice
    The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)

    @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:
                    IJBPaymentTerminal terminal;
                    address holder;
                    uint256 projectId;
                    uint256 currentFundingCycleConfiguration;
                    uint256 tokenCount;
                    uint256 totalSupply;
                    uint256 overflow;
                    JBTokenAmount reclaimAmount;
                    bool useTotalOverflow;
                    uint256 redemptionRate;
                    uint256 ballotRedemptionRate;
                    string memo;
                    bytes metadata;

    @return reclaimAmount The amount to claim, overriding the terminal logic.
    @return memo The memo to override the redeemTokensOf(..) memo.
    @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.
  */
  function redeemParams(JBRedeemParamsData calldata _data)
    external
    returns (
      uint256 reclaimAmount,
      string memory memo,
      JBRedemptionDelegateAllocation[] memory delegateAllocations
    );
}

File 11 of 47 : IJBFundingCycleStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../enums/JBBallotState.sol';
import './../structs/JBFundingCycle.sol';
import './../structs/JBFundingCycleData.sol';

interface IJBFundingCycleStore {
  event Configure(
    uint256 indexed configuration,
    uint256 indexed projectId,
    JBFundingCycleData data,
    uint256 metadata,
    uint256 mustStartAtOrAfter,
    address caller
  );

  event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);

  function latestConfigurationOf(uint256 _projectId) external view returns (uint256);

  function get(uint256 _projectId, uint256 _configuration)
    external
    view
    returns (JBFundingCycle memory);

  function latestConfiguredOf(uint256 _projectId)
    external
    view
    returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);

  function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);

  function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);

  function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);

  function configureFor(
    uint256 _projectId,
    JBFundingCycleData calldata _data,
    uint256 _metadata,
    uint256 _mustStartAtOrAfter
  ) external returns (JBFundingCycle memory fundingCycle);
}

File 12 of 47 : IJBMigratable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJBMigratable {
  function prepForMigrationOf(uint256 _projectId, address _from) external;
}

File 13 of 47 : IJBPayDelegate.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import './../structs/JBDidPayData.sol';

/**
  @title
  Pay delegate

  @notice
  Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)

  @dev
  Adheres to:
  IERC165 for adequate interface integration
*/
interface IJBPayDelegate is IERC165 {
  /**
    @notice
    This function is called by JBPaymentTerminal.pay(..), after the execution of its logic

    @dev
    Critical business logic should be protected by an appropriate access control
    
    @param _data the data passed by the terminal, as a JBDidPayData struct:
                  address payer;
                  uint256 projectId;
                  uint256 currentFundingCycleConfiguration;
                  JBTokenAmount amount;
                  JBTokenAmount forwardedAmount;
                  uint256 projectTokenCount;
                  address beneficiary;
                  bool preferClaimedTokens;
                  string memo;
                  bytes metadata;
  */
  function didPay(JBDidPayData calldata _data) external payable;
}

File 14 of 47 : IJBPaymentTerminal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/IERC165.sol';

interface IJBPaymentTerminal is IERC165 {
  function acceptsToken(address _token, uint256 _projectId) external view returns (bool);

  function currencyForToken(address _token) external view returns (uint256);

  function decimalsForToken(address _token) external view returns (uint256);

  // Return value must be a fixed point number with 18 decimals.
  function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);

  function pay(
    uint256 _projectId,
    uint256 _amount,
    address _token,
    address _beneficiary,
    uint256 _minReturnedTokens,
    bool _preferClaimedTokens,
    string calldata _memo,
    bytes calldata _metadata
  ) external payable returns (uint256 beneficiaryTokenCount);

  function addToBalanceOf(
    uint256 _projectId,
    uint256 _amount,
    address _token,
    string calldata _memo,
    bytes calldata _metadata
  ) external payable;
}

File 15 of 47 : IJBPriceFeed.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJBPriceFeed {
  function currentPrice(uint256 _targetDecimals) external view returns (uint256);
}

File 16 of 47 : IJBPrices.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './IJBPriceFeed.sol';

interface IJBPrices {
  event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);

  function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);

  function priceFor(
    uint256 _currency,
    uint256 _base,
    uint256 _decimals
  ) external view returns (uint256);

  function addFeedFor(
    uint256 _currency,
    uint256 _base,
    IJBPriceFeed _priceFeed
  ) external;
}

File 17 of 47 : IJBProjects.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import './../structs/JBProjectMetadata.sol';
import './IJBTokenUriResolver.sol';

interface IJBProjects is IERC721 {
  event Create(
    uint256 indexed projectId,
    address indexed owner,
    JBProjectMetadata metadata,
    address caller
  );

  event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);

  event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);

  function count() external view returns (uint256);

  function metadataContentOf(uint256 _projectId, uint256 _domain)
    external
    view
    returns (string memory);

  function tokenUriResolver() external view returns (IJBTokenUriResolver);

  function createFor(address _owner, JBProjectMetadata calldata _metadata)
    external
    returns (uint256 projectId);

  function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;

  function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;
}

File 18 of 47 : IJBRedemptionDelegate.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import './../structs/JBDidRedeemData.sol';

/**
  @title
  Redemption delegate

  @notice
  Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)

  @dev
  Adheres to:
  IERC165 for adequate interface integration
*/
interface IJBRedemptionDelegate is IERC165 {
  /**
    @notice
    This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic

    @dev
    Critical business logic should be protected by an appropriate access control
    
    @param _data the data passed by the terminal, as a JBDidRedeemData struct:
                address holder;
                uint256 projectId;
                uint256 currentFundingCycleConfiguration;
                uint256 projectTokenCount;
                JBTokenAmount reclaimedAmount;
                JBTokenAmount forwardedAmount;
                address payable beneficiary;
                string memo;
                bytes metadata;
  */
  function didRedeem(JBDidRedeemData calldata _data) external payable;
}

File 19 of 47 : IJBSingleTokenPaymentTerminal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './IJBPaymentTerminal.sol';

interface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {
  function token() external view returns (address);

  function currency() external view returns (uint256);

  function decimals() external view returns (uint256);
}

File 20 of 47 : IJBSingleTokenPaymentTerminalStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../structs/JBFundingCycle.sol';
import './../structs/JBPayDelegateAllocation.sol';
import './../structs/JBRedemptionDelegateAllocation.sol';
import './../structs/JBTokenAmount.sol';
import './IJBDirectory.sol';
import './IJBFundingCycleStore.sol';
import './IJBPrices.sol';
import './IJBSingleTokenPaymentTerminal.sol';

interface IJBSingleTokenPaymentTerminalStore {
  function fundingCycleStore() external view returns (IJBFundingCycleStore);

  function directory() external view returns (IJBDirectory);

  function prices() external view returns (IJBPrices);

  function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)
    external
    view
    returns (uint256);

  function usedDistributionLimitOf(
    IJBSingleTokenPaymentTerminal _terminal,
    uint256 _projectId,
    uint256 _fundingCycleNumber
  ) external view returns (uint256);

  function usedOverflowAllowanceOf(
    IJBSingleTokenPaymentTerminal _terminal,
    uint256 _projectId,
    uint256 _fundingCycleConfiguration
  ) external view returns (uint256);

  function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)
    external
    view
    returns (uint256);

  function currentTotalOverflowOf(
    uint256 _projectId,
    uint256 _decimals,
    uint256 _currency
  ) external view returns (uint256);

  function currentReclaimableOverflowOf(
    IJBSingleTokenPaymentTerminal _terminal,
    uint256 _projectId,
    uint256 _tokenCount,
    bool _useTotalOverflow
  ) external view returns (uint256);

  function currentReclaimableOverflowOf(
    uint256 _projectId,
    uint256 _tokenCount,
    uint256 _totalSupply,
    uint256 _overflow
  ) external view returns (uint256);

  function recordPaymentFrom(
    address _payer,
    JBTokenAmount memory _amount,
    uint256 _projectId,
    uint256 _baseWeightCurrency,
    address _beneficiary,
    string calldata _memo,
    bytes calldata _metadata
  )
    external
    returns (
      JBFundingCycle memory fundingCycle,
      uint256 tokenCount,
      JBPayDelegateAllocation[] memory delegateAllocations,
      string memory memo
    );

  function recordRedemptionFor(
    address _holder,
    uint256 _projectId,
    uint256 _tokenCount,
    string calldata _memo,
    bytes calldata _metadata
  )
    external
    returns (
      JBFundingCycle memory fundingCycle,
      uint256 reclaimAmount,
      JBRedemptionDelegateAllocation[] memory delegateAllocations,
      string memory memo
    );

  function recordDistributionFor(
    uint256 _projectId,
    uint256 _amount,
    uint256 _currency
  ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);

  function recordUsedAllowanceOf(
    uint256 _projectId,
    uint256 _amount,
    uint256 _currency
  ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);

  function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;

  function recordMigration(uint256 _projectId) external returns (uint256 balance);
}

File 21 of 47 : IJBSplitAllocator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import '../structs/JBSplitAllocationData.sol';

/**
  @title
  Split allocator

  @notice
  Provide a way to process a single split with extra logic

  @dev
  Adheres to:
  IERC165 for adequate interface integration

  @dev
  The contract address should be set as an allocator in the adequate split
*/
interface IJBSplitAllocator is IERC165 {
  /**
    @notice
    This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it

    @dev
    Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered
    to the allocator for its logic.
    
    @param _data the data passed by the terminal, as a JBSplitAllocationData struct:
                  address token;
                  uint256 amount;
                  uint256 decimals;
                  uint256 projectId;
                  uint256 group;
                  JBSplit split;
  */
  function allocate(JBSplitAllocationData calldata _data) external payable;
}

File 22 of 47 : IJBSplitsStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../structs/JBGroupedSplits.sol';
import './../structs/JBSplit.sol';
import './IJBDirectory.sol';
import './IJBProjects.sol';

interface IJBSplitsStore {
  event SetSplit(
    uint256 indexed projectId,
    uint256 indexed domain,
    uint256 indexed group,
    JBSplit split,
    address caller
  );

  function projects() external view returns (IJBProjects);

  function directory() external view returns (IJBDirectory);

  function splitsOf(
    uint256 _projectId,
    uint256 _domain,
    uint256 _group
  ) external view returns (JBSplit[] memory);

  function set(
    uint256 _projectId,
    uint256 _domain,
    JBGroupedSplits[] memory _groupedSplits
  ) external;
}

File 23 of 47 : IJBToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJBToken {
  function projectId() external view returns (uint256);

  function decimals() external view returns (uint8);

  function totalSupply(uint256 _projectId) external view returns (uint256);

  function balanceOf(address _account, uint256 _projectId) external view returns (uint256);

  function mint(
    uint256 _projectId,
    address _account,
    uint256 _amount
  ) external;

  function burn(
    uint256 _projectId,
    address _account,
    uint256 _amount
  ) external;

  function approve(
    uint256,
    address _spender,
    uint256 _amount
  ) external;

  function transfer(
    uint256 _projectId,
    address _to,
    uint256 _amount
  ) external;

  function transferFrom(
    uint256 _projectId,
    address _from,
    address _to,
    uint256 _amount
  ) external;
}

File 24 of 47 : IJBTokenStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './IJBFundingCycleStore.sol';
import './IJBProjects.sol';
import './IJBToken.sol';

interface IJBTokenStore {
  event Issue(
    uint256 indexed projectId,
    IJBToken indexed token,
    string name,
    string symbol,
    address caller
  );

  event Mint(
    address indexed holder,
    uint256 indexed projectId,
    uint256 amount,
    bool tokensWereClaimed,
    bool preferClaimedTokens,
    address caller
  );

  event Burn(
    address indexed holder,
    uint256 indexed projectId,
    uint256 amount,
    uint256 initialUnclaimedBalance,
    uint256 initialClaimedBalance,
    bool preferClaimedTokens,
    address caller
  );

  event Claim(
    address indexed holder,
    uint256 indexed projectId,
    uint256 initialUnclaimedBalance,
    uint256 amount,
    address caller
  );

  event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);

  event Transfer(
    address indexed holder,
    uint256 indexed projectId,
    address indexed recipient,
    uint256 amount,
    address caller
  );

  function tokenOf(uint256 _projectId) external view returns (IJBToken);

  function projects() external view returns (IJBProjects);

  function fundingCycleStore() external view returns (IJBFundingCycleStore);

  function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);

  function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);

  function totalSupplyOf(uint256 _projectId) external view returns (uint256);

  function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);

  function issueFor(
    uint256 _projectId,
    string calldata _name,
    string calldata _symbol
  ) external returns (IJBToken token);

  function setFor(uint256 _projectId, IJBToken _token) external;

  function burnFrom(
    address _holder,
    uint256 _projectId,
    uint256 _amount,
    bool _preferClaimedTokens
  ) external;

  function mintFor(
    address _holder,
    uint256 _projectId,
    uint256 _amount,
    bool _preferClaimedTokens
  ) external;

  function claimFor(
    address _holder,
    uint256 _projectId,
    uint256 _amount
  ) external;

  function transferFrom(
    address _holder,
    uint256 _projectId,
    address _recipient,
    uint256 _amount
  ) external;
}

File 25 of 47 : IJBTokenUriResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJBTokenUriResolver {
  function getUri(uint256 _projectId) external view returns (string memory tokenUri);
}

File 26 of 47 : JBConstants.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
  @notice
  Global constants used across Juicebox contracts.
*/
library JBConstants {
  uint256 public constant MAX_RESERVED_RATE = 10_000;
  uint256 public constant MAX_REDEMPTION_RATE = 10_000;
  uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;
  uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;
  uint256 public constant MAX_FEE = 1_000_000_000;
  uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;
}

File 27 of 47 : JBCurrencies.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library JBCurrencies {
  uint256 public constant ETH = 1;
  uint256 public constant USD = 2;
}

File 28 of 47 : JBFixedPointNumber.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

library JBFixedPointNumber {
  function adjustDecimals(
    uint256 _value,
    uint256 _decimals,
    uint256 _targetDecimals
  ) internal pure returns (uint256) {
    // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.
    if (_targetDecimals == _decimals) return _value;
    else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);
    else return _value / 10**(_decimals - _targetDecimals);
  }
}

File 29 of 47 : JBFundingCycleMetadataResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import './../structs/JBFundingCycle.sol';
import './../structs/JBFundingCycleMetadata.sol';
import './../structs/JBGlobalFundingCycleMetadata.sol';
import './JBConstants.sol';
import './JBGlobalFundingCycleMetadataResolver.sol';

library JBFundingCycleMetadataResolver {
  function global(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (JBGlobalFundingCycleMetadata memory)
  {
    return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));
  }

  function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {
    return uint256(uint16(_fundingCycle.metadata >> 24));
  }

  function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {
    // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.
    return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));
  }

  function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (uint256)
  {
    // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.
    return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));
  }

  function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {
    return ((_fundingCycle.metadata >> 72) & 1) == 1;
  }

  function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {
    return ((_fundingCycle.metadata >> 73) & 1) == 1;
  }

  function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {
    return ((_fundingCycle.metadata >> 74) & 1) == 1;
  }

  function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {
    return ((_fundingCycle.metadata >> 75) & 1) == 1;
  }

  function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {
    return ((_fundingCycle.metadata >> 76) & 1) == 1;
  }

  function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (bool)
  {
    return ((_fundingCycle.metadata >> 77) & 1) == 1;
  }

  function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (bool)
  {
    return ((_fundingCycle.metadata >> 78) & 1) == 1;
  }

  function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {
    return ((_fundingCycle.metadata >> 79) & 1) == 1;
  }

  function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (bool)
  {
    return ((_fundingCycle.metadata >> 80) & 1) == 1;
  }

  function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (bool)
  {
    return ((_fundingCycle.metadata >> 81) & 1) == 1;
  }

  function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {
    return (_fundingCycle.metadata >> 82) & 1 == 1;
  }

  function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (bool)
  {
    return (_fundingCycle.metadata >> 83) & 1 == 1;
  }

  function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {
    return address(uint160(_fundingCycle.metadata >> 84));
  }

  function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {
    return uint256(uint8(_fundingCycle.metadata >> 244));
  }

  /**
    @notice
    Pack the funding cycle metadata.

    @param _metadata The metadata to validate and pack.

    @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.
  */
  function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)
    internal
    pure
    returns (uint256 packed)
  {
    // version 1 in the bits 0-7 (8 bits).
    packed = 1;
    // global metadta in bits 8-23 (16 bits).
    packed |=
      JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<
      8;
    // reserved rate in bits 24-39 (16 bits).
    packed |= _metadata.reservedRate << 24;
    // redemption rate in bits 40-55 (16 bits).
    // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.
    packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;
    // ballot redemption rate rate in bits 56-71 (16 bits).
    // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.
    packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;
    // pause pay in bit 72.
    if (_metadata.pausePay) packed |= 1 << 72;
    // pause tap in bit 73.
    if (_metadata.pauseDistributions) packed |= 1 << 73;
    // pause redeem in bit 74.
    if (_metadata.pauseRedeem) packed |= 1 << 74;
    // pause burn in bit 75.
    if (_metadata.pauseBurn) packed |= 1 << 75;
    // allow minting in bit 76.
    if (_metadata.allowMinting) packed |= 1 << 76;
    // allow terminal migration in bit 77.
    if (_metadata.allowTerminalMigration) packed |= 1 << 77;
    // allow controller migration in bit 78.
    if (_metadata.allowControllerMigration) packed |= 1 << 78;
    // hold fees in bit 79.
    if (_metadata.holdFees) packed |= 1 << 79;
    // prefer claimed token override in bit 80.
    if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;
    // useTotalOverflowForRedemptions in bit 81.
    if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;
    // use pay data source in bit 82.
    if (_metadata.useDataSourceForPay) packed |= 1 << 82;
    // use redeem data source in bit 83.
    if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;
    // data source address in bits 84-243.
    packed |= uint256(uint160(address(_metadata.dataSource))) << 84;
    // metadata in bits 244-252 (8 bits).
    packed |= _metadata.metadata << 244;
  }

  /**
    @notice
    Expand the funding cycle metadata.

    @param _fundingCycle The funding cycle having its metadata expanded.

    @return metadata The metadata object.
  */
  function expandMetadata(JBFundingCycle memory _fundingCycle)
    internal
    pure
    returns (JBFundingCycleMetadata memory)
  {
    return
      JBFundingCycleMetadata(
        global(_fundingCycle),
        reservedRate(_fundingCycle),
        redemptionRate(_fundingCycle),
        ballotRedemptionRate(_fundingCycle),
        payPaused(_fundingCycle),
        distributionsPaused(_fundingCycle),
        redeemPaused(_fundingCycle),
        burnPaused(_fundingCycle),
        mintingAllowed(_fundingCycle),
        terminalMigrationAllowed(_fundingCycle),
        controllerMigrationAllowed(_fundingCycle),
        shouldHoldFees(_fundingCycle),
        preferClaimedTokenOverride(_fundingCycle),
        useTotalOverflowForRedemptions(_fundingCycle),
        useDataSourceForPay(_fundingCycle),
        useDataSourceForRedeem(_fundingCycle),
        dataSource(_fundingCycle),
        metadata(_fundingCycle)
      );
  }
}

File 30 of 47 : JBGlobalFundingCycleMetadataResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import './../structs/JBFundingCycleMetadata.sol';

library JBGlobalFundingCycleMetadataResolver {
  function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {
    return (_data & 1) == 1;
  }

  function setControllerAllowed(uint8 _data) internal pure returns (bool) {
    return ((_data >> 1) & 1) == 1;
  }

  function transfersPaused(uint8 _data) internal pure returns (bool) {
    return ((_data >> 2) & 1) == 1;
  }

  /**
    @notice
    Pack the global funding cycle metadata.

    @param _metadata The metadata to validate and pack.

    @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.
  */
  function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)
    internal
    pure
    returns (uint256 packed)
  {
    // allow set terminals in bit 0.
    if (_metadata.allowSetTerminals) packed |= 1;
    // allow set controller in bit 1.
    if (_metadata.allowSetController) packed |= 1 << 1;
    // pause transfers in bit 2.
    if (_metadata.pauseTransfers) packed |= 1 << 2;
  }

  /**
    @notice
    Expand the global funding cycle metadata.

    @param _packedMetadata The packed metadata to expand.

    @return metadata The global metadata object.
  */
  function expandMetadata(uint8 _packedMetadata)
    internal
    pure
    returns (JBGlobalFundingCycleMetadata memory metadata)
  {
    return
      JBGlobalFundingCycleMetadata(
        setTerminalsAllowed(_packedMetadata),
        setControllerAllowed(_packedMetadata),
        transfersPaused(_packedMetadata)
      );
  }
}

File 31 of 47 : JBDidPayData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './JBTokenAmount.sol';

/** 
  @member payer The address from which the payment originated.
  @member projectId The ID of the project for which the payment was made.
  @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.
  @member amount The amount of the payment. Includes the token being paid, the value, the number of decimals included, and the currency of the amount.
  @member forwardedAmount The amount of the payment that is being sent to the delegate. Includes the token being paid, the value, the number of decimals included, and the currency of the amount.
  @member projectTokenCount The number of project tokens minted for the beneficiary.
  @member beneficiary The address to which the tokens were minted.
  @member preferClaimedTokens A flag indicating whether the request prefered to mint project tokens into the beneficiaries wallet rather than leaving them unclaimed. This is only possible if the project has an attached token contract.
  @member memo The memo that is being emitted alongside the payment.
  @member metadata Extra data to send to the delegate.
*/
struct JBDidPayData {
  address payer;
  uint256 projectId;
  uint256 currentFundingCycleConfiguration;
  JBTokenAmount amount;
  JBTokenAmount forwardedAmount;
  uint256 projectTokenCount;
  address beneficiary;
  bool preferClaimedTokens;
  string memo;
  bytes metadata;
}

File 32 of 47 : JBDidRedeemData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './JBTokenAmount.sol';

/** 
  @member holder The holder of the tokens being redeemed.
  @member projectId The ID of the project with which the redeemed tokens are associated.
  @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.
  @member projectTokenCount The number of project tokens being redeemed.
  @member reclaimedAmount The amount reclaimed from the treasury. Includes the token being reclaimed, the value, the number of decimals included, and the currency of the amount.
  @member forwardedAmount The amount of the payment that is being sent to the delegate. Includes the token being paid, the value, the number of decimals included, and the currency of the amount.
  @member beneficiary The address to which the reclaimed amount will be sent.
  @member memo The memo that is being emitted alongside the redemption.
  @member metadata Extra data to send to the delegate.
*/
struct JBDidRedeemData {
  address holder;
  uint256 projectId;
  uint256 currentFundingCycleConfiguration;
  uint256 projectTokenCount;
  JBTokenAmount reclaimedAmount;
  JBTokenAmount forwardedAmount;
  address payable beneficiary;
  string memo;
  bytes metadata;
}

File 33 of 47 : JBFundAccessConstraints.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../interfaces/IJBPaymentTerminal.sol';

/** 
  @member terminal The terminal within which the distribution limit and the overflow allowance applies.
  @member token The token for which the fund access constraints apply.
  @member distributionLimit The amount of the distribution limit, as a fixed point number with the same number of decimals as the terminal within which the limit applies.
  @member distributionLimitCurrency The currency of the distribution limit.
  @member overflowAllowance The amount of the allowance, as a fixed point number with the same number of decimals as the terminal within which the allowance applies.
  @member overflowAllowanceCurrency The currency of the overflow allowance.
*/
struct JBFundAccessConstraints {
  IJBPaymentTerminal terminal;
  address token;
  uint256 distributionLimit;
  uint256 distributionLimitCurrency;
  uint256 overflowAllowance;
  uint256 overflowAllowanceCurrency;
}

File 34 of 47 : JBFundingCycle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../interfaces/IJBFundingCycleBallot.sol';

/** 
  @member number The funding cycle number for the cycle's project. Each funding cycle has a number that is an increment of the cycle that directly preceded it. Each project's first funding cycle has a number of 1.
  @member configuration The timestamp when the parameters for this funding cycle were configured. This value will stay the same for subsequent funding cycles that roll over from an originally configured cycle.
  @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.
  @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.
  @member duration The number of seconds the funding cycle lasts for, after which a new funding cycle will start. A duration of 0 means that the funding cycle will stay active until the project owner explicitly issues a reconfiguration, at which point a new funding cycle will immediately start with the updated properties. If the duration is greater than 0, a project owner cannot make changes to a funding cycle's parameters while it is active – any proposed changes will apply to the subsequent cycle. If no changes are proposed, a funding cycle rolls over to another one with the same properties but new `start` timestamp and a discounted `weight`.
  @member weight A fixed point number with 18 decimals that contracts can use to base arbitrary calculations on. For example, payment terminals can use this to determine how many tokens should be minted when a payment is received.
  @member discountRate A percent by how much the `weight` of the subsequent funding cycle should be reduced, if the project owner hasn't configured the subsequent funding cycle with an explicit `weight`. If it's 0, each funding cycle will have equal weight. If the number is 90%, the next funding cycle will have a 10% smaller weight. This weight is out of `JBConstants.MAX_DISCOUNT_RATE`.
  @member ballot An address of a contract that says whether a proposed reconfiguration should be accepted or rejected. It can be used to create rules around how a project owner can change funding cycle parameters over time.
  @member metadata Extra data that can be associated with a funding cycle.
*/
struct JBFundingCycle {
  uint256 number;
  uint256 configuration;
  uint256 basedOn;
  uint256 start;
  uint256 duration;
  uint256 weight;
  uint256 discountRate;
  IJBFundingCycleBallot ballot;
  uint256 metadata;
}

File 35 of 47 : JBFundingCycleData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../interfaces/IJBFundingCycleBallot.sol';

/** 
  @member duration The number of seconds the funding cycle lasts for, after which a new funding cycle will start. A duration of 0 means that the funding cycle will stay active until the project owner explicitly issues a reconfiguration, at which point a new funding cycle will immediately start with the updated properties. If the duration is greater than 0, a project owner cannot make changes to a funding cycle's parameters while it is active – any proposed changes will apply to the subsequent cycle. If no changes are proposed, a funding cycle rolls over to another one with the same properties but new `start` timestamp and a discounted `weight`.
  @member weight A fixed point number with 18 decimals that contracts can use to base arbitrary calculations on. For example, payment terminals can use this to determine how many tokens should be minted when a payment is received.
  @member discountRate A percent by how much the `weight` of the subsequent funding cycle should be reduced, if the project owner hasn't configured the subsequent funding cycle with an explicit `weight`. If it's 0, each funding cycle will have equal weight. If the number is 90%, the next funding cycle will have a 10% smaller weight. This weight is out of `JBConstants.MAX_DISCOUNT_RATE`.
  @member ballot An address of a contract that says whether a proposed reconfiguration should be accepted or rejected. It can be used to create rules around how a project owner can change funding cycle parameters over time.
*/
struct JBFundingCycleData {
  uint256 duration;
  uint256 weight;
  uint256 discountRate;
  IJBFundingCycleBallot ballot;
}

File 36 of 47 : JBFundingCycleMetadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './JBGlobalFundingCycleMetadata.sol';

/** 
  @member global Data used globally in non-migratable ecosystem contracts.
  @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.
  @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.
  @member ballotRedemptionRate The redemption rate to use during an active ballot of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.
  @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.
  @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.
  @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.
  @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.
  @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.
  @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.
  @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.
  @member holdFees A flag indicating if fees should be held during this funding cycle.
  @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.
  @member useTotalOverflowForRedemptions A flag indicating if redemptions should use the project's balance held in all terminals instead of the project's local terminal balance from which the redemption is being fulfilled.
  @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.
  @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.
  @member dataSource The data source to use during this funding cycle.
  @member metadata Metadata of the metadata, up to uint8 in size.
*/
struct JBFundingCycleMetadata {
  JBGlobalFundingCycleMetadata global;
  uint256 reservedRate;
  uint256 redemptionRate;
  uint256 ballotRedemptionRate;
  bool pausePay;
  bool pauseDistributions;
  bool pauseRedeem;
  bool pauseBurn;
  bool allowMinting;
  bool allowTerminalMigration;
  bool allowControllerMigration;
  bool holdFees;
  bool preferClaimedTokenOverride;
  bool useTotalOverflowForRedemptions;
  bool useDataSourceForPay;
  bool useDataSourceForRedeem;
  address dataSource;
  uint256 metadata;
}

File 37 of 47 : JBGlobalFundingCycleMetadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/** 
  @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.
  @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.
  @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.
*/
struct JBGlobalFundingCycleMetadata {
  bool allowSetTerminals;
  bool allowSetController;
  bool pauseTransfers;
}

File 38 of 47 : JBGroupedSplits.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './JBSplit.sol';

/** 
  @member group The group indentifier.
  @member splits The splits to associate with the group.
*/
struct JBGroupedSplits {
  uint256 group;
  JBSplit[] splits;
}

File 39 of 47 : JBPayDelegateAllocation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '../interfaces/IJBPayDelegate.sol';

/** 
 @member delegate A delegate contract to use for subsequent calls.
 @member amount The amount to send to the delegate.
*/
struct JBPayDelegateAllocation {
  IJBPayDelegate delegate;
  uint256 amount;
}

File 40 of 47 : JBPayParamsData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../interfaces/IJBPaymentTerminal.sol';
import './JBTokenAmount.sol';

/** 
  @member terminal The terminal that is facilitating the payment.
  @member payer The address from which the payment originated.
  @member amount The amount of the payment. Includes the token being paid, the value, the number of decimals included, and the currency of the amount.
  @member projectId The ID of the project being paid.
  @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.
  @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.
  @member weight The weight of the funding cycle during which the payment is being made.
  @member reservedRate The reserved rate of the funding cycle during which the payment is being made.
  @member memo The memo that was sent alongside the payment.
  @member metadata Extra data provided by the payer.
*/
struct JBPayParamsData {
  IJBPaymentTerminal terminal;
  address payer;
  JBTokenAmount amount;
  uint256 projectId;
  uint256 currentFundingCycleConfiguration;
  address beneficiary;
  uint256 weight;
  uint256 reservedRate;
  string memo;
  bytes metadata;
}

File 41 of 47 : JBProjectMetadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/** 
  @member content The metadata content.
  @member domain The domain within which the metadata applies.
*/
struct JBProjectMetadata {
  string content;
  uint256 domain;
}

File 42 of 47 : JBRedeemParamsData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../interfaces/IJBPaymentTerminal.sol';
import './JBTokenAmount.sol';

/** 
  @member terminal The terminal that is facilitating the redemption.
  @member holder The holder of the tokens being redeemed.
  @member projectId The ID of the project whos tokens are being redeemed.
  @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.
  @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.
  @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.
  @member overflow The amount of overflow used in the reclaim amount calculation.
  @member reclaimAmount The amount that should be reclaimed by the redeemer using the protocol's standard bonding curve redemption formula. Includes the token being reclaimed, the reclaim value, the number of decimals included, and the currency of the reclaim amount.
  @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.
  @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.
  @member memo The proposed memo that is being emitted alongside the redemption.
  @member metadata Extra data provided by the redeemer.
*/
struct JBRedeemParamsData {
  IJBPaymentTerminal terminal;
  address holder;
  uint256 projectId;
  uint256 currentFundingCycleConfiguration;
  uint256 tokenCount;
  uint256 totalSupply;
  uint256 overflow;
  JBTokenAmount reclaimAmount;
  bool useTotalOverflow;
  uint256 redemptionRate;
  string memo;
  bytes metadata;
}

File 43 of 47 : JBRedemptionDelegateAllocation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '../interfaces/IJBRedemptionDelegate.sol';

/** 
 @member delegate A delegate contract to use for subsequent calls.
 @member amount The amount to send to the delegate.
*/
struct JBRedemptionDelegateAllocation {
  IJBRedemptionDelegate delegate;
  uint256 amount;
}

File 44 of 47 : JBSplit.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './../interfaces/IJBSplitAllocator.sol';

/** 
  @member preferClaimed A flag that only has effect if a projectId is also specified, and the project has a token contract attached. If so, this flag indicates if the tokens that result from making a payment to the project should be delivered claimed into the beneficiary's wallet, or unclaimed to save gas.
  @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.
  @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.
  @member projectId The ID of a project. If an allocator is not set but a projectId is set, funds will be sent to the protocol treasury belonging to the project who's ID is specified. Resulting tokens will be routed to the beneficiary with the claimed token preference respected.
  @member beneficiary An address. The role the of the beneficary depends on whether or not projectId is specified, and whether or not an allocator is specified. If allocator is set, the beneficiary will be forwarded to the allocator for it to use. If allocator is not set but projectId is set, the beneficiary is the address to which the project's tokens will be sent that result from a payment to it. If neither allocator or projectId are set, the beneficiary is where the funds from the split will be sent.
  @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.
  @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.
*/
struct JBSplit {
  bool preferClaimed;
  bool preferAddToBalance;
  uint256 percent;
  uint256 projectId;
  address payable beneficiary;
  uint256 lockedUntil;
  IJBSplitAllocator allocator;
}

File 45 of 47 : JBSplitAllocationData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './JBSplit.sol';

/** 
  @member token The token being sent to the split allocator.
  @member amount The amount being sent to the split allocator, as a fixed point number.
  @member decimals The number of decimals in the amount.
  @member projectId The project to which the split belongs.
  @member group The group to which the split belongs.
  @member split The split that caused the allocation.
*/
struct JBSplitAllocationData {
  address token;
  uint256 amount;
  uint256 decimals;
  uint256 projectId;
  uint256 group;
  JBSplit split;
}

File 46 of 47 : JBTokenAmount.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/* 
  @member token The token the payment was made in.
  @member value The amount of tokens that was paid, as a fixed point number.
  @member decimals The number of decimals included in the value fixed point number.
  @member currency The expected currency of the value.
**/
struct JBTokenAmount {
  address token;
  uint256 value;
  uint256 decimals;
  uint256 currency;
}

File 47 of 47 : PRBMath.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivFixedPointOverflow(uint256 prod1);

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);

/// @notice Emitted when one of the inputs is type(int256).min.
error PRBMath__MulDivSignedInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows int256.
error PRBMath__MulDivSignedOverflow(uint256 rAbs);

/// @notice Emitted when the input is MIN_SD59x18.
error PRBMathSD59x18__AbsInputTooSmall();

/// @notice Emitted when ceiling a number overflows SD59x18.
error PRBMathSD59x18__CeilOverflow(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__DivInputTooSmall();

/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.
error PRBMathSD59x18__DivOverflow(uint256 rAbs);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathSD59x18__ExpInputTooBig(int256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathSD59x18__Exp2InputTooBig(int256 x);

/// @notice Emitted when flooring a number underflows SD59x18.
error PRBMathSD59x18__FloorUnderflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.
error PRBMathSD59x18__FromIntOverflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.
error PRBMathSD59x18__FromIntUnderflow(int256 x);

/// @notice Emitted when the product of the inputs is negative.
error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);

/// @notice Emitted when multiplying the inputs overflows SD59x18.
error PRBMathSD59x18__GmOverflow(int256 x, int256 y);

/// @notice Emitted when the input is less than or equal to zero.
error PRBMathSD59x18__LogInputTooSmall(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__MulInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__MulOverflow(uint256 rAbs);

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__PowuOverflow(uint256 rAbs);

/// @notice Emitted when the input is negative.
error PRBMathSD59x18__SqrtNegativeInput(int256 x);

/// @notice Emitted when the calculating the square root overflows SD59x18.
error PRBMathSD59x18__SqrtOverflow(int256 x);

/// @notice Emitted when addition overflows UD60x18.
error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);

/// @notice Emitted when ceiling a number overflows UD60x18.
error PRBMathUD60x18__CeilOverflow(uint256 x);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathUD60x18__ExpInputTooBig(uint256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathUD60x18__Exp2InputTooBig(uint256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.
error PRBMathUD60x18__FromUintOverflow(uint256 x);

/// @notice Emitted when multiplying the inputs overflows UD60x18.
error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);

/// @notice Emitted when the input is less than 1.
error PRBMathUD60x18__LogInputTooSmall(uint256 x);

/// @notice Emitted when the calculating the square root overflows UD60x18.
error PRBMathUD60x18__SqrtOverflow(uint256 x);

/// @notice Emitted when subtraction underflows UD60x18.
error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);

/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library
/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point
/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.
library PRBMath {
    /// STRUCTS ///

    struct SD59x18 {
        int256 value;
    }

    struct UD60x18 {
        uint256 value;
    }

    /// STORAGE ///

    /// @dev How many trailing decimals can be represented.
    uint256 internal constant SCALE = 1e18;

    /// @dev Largest power of two divisor of SCALE.
    uint256 internal constant SCALE_LPOTD = 262144;

    /// @dev SCALE inverted mod 2^256.
    uint256 internal constant SCALE_INVERSE =
        78156646155174841979727994598816262306175212592076161876661_508869554232690281;

    /// FUNCTIONS ///

    /// @notice Calculates the binary exponent of x using the binary fraction method.
    /// @dev Has to use 192.64-bit fixed-point numbers.
    /// See https://ethereum.stackexchange.com/a/96594/24693.
    /// @param x The exponent as an unsigned 192.64-bit fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function exp2(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            // Start from 0.5 in the 192.64-bit fixed-point format.
            result = 0x800000000000000000000000000000000000000000000000;

            // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows
            // because the initial result is 2^191 and all magic factors are less than 2^65.
            if (x & 0x8000000000000000 > 0) {
                result = (result * 0x16A09E667F3BCC909) >> 64;
            }
            if (x & 0x4000000000000000 > 0) {
                result = (result * 0x1306FE0A31B7152DF) >> 64;
            }
            if (x & 0x2000000000000000 > 0) {
                result = (result * 0x1172B83C7D517ADCE) >> 64;
            }
            if (x & 0x1000000000000000 > 0) {
                result = (result * 0x10B5586CF9890F62A) >> 64;
            }
            if (x & 0x800000000000000 > 0) {
                result = (result * 0x1059B0D31585743AE) >> 64;
            }
            if (x & 0x400000000000000 > 0) {
                result = (result * 0x102C9A3E778060EE7) >> 64;
            }
            if (x & 0x200000000000000 > 0) {
                result = (result * 0x10163DA9FB33356D8) >> 64;
            }
            if (x & 0x100000000000000 > 0) {
                result = (result * 0x100B1AFA5ABCBED61) >> 64;
            }
            if (x & 0x80000000000000 > 0) {
                result = (result * 0x10058C86DA1C09EA2) >> 64;
            }
            if (x & 0x40000000000000 > 0) {
                result = (result * 0x1002C605E2E8CEC50) >> 64;
            }
            if (x & 0x20000000000000 > 0) {
                result = (result * 0x100162F3904051FA1) >> 64;
            }
            if (x & 0x10000000000000 > 0) {
                result = (result * 0x1000B175EFFDC76BA) >> 64;
            }
            if (x & 0x8000000000000 > 0) {
                result = (result * 0x100058BA01FB9F96D) >> 64;
            }
            if (x & 0x4000000000000 > 0) {
                result = (result * 0x10002C5CC37DA9492) >> 64;
            }
            if (x & 0x2000000000000 > 0) {
                result = (result * 0x1000162E525EE0547) >> 64;
            }
            if (x & 0x1000000000000 > 0) {
                result = (result * 0x10000B17255775C04) >> 64;
            }
            if (x & 0x800000000000 > 0) {
                result = (result * 0x1000058B91B5BC9AE) >> 64;
            }
            if (x & 0x400000000000 > 0) {
                result = (result * 0x100002C5C89D5EC6D) >> 64;
            }
            if (x & 0x200000000000 > 0) {
                result = (result * 0x10000162E43F4F831) >> 64;
            }
            if (x & 0x100000000000 > 0) {
                result = (result * 0x100000B1721BCFC9A) >> 64;
            }
            if (x & 0x80000000000 > 0) {
                result = (result * 0x10000058B90CF1E6E) >> 64;
            }
            if (x & 0x40000000000 > 0) {
                result = (result * 0x1000002C5C863B73F) >> 64;
            }
            if (x & 0x20000000000 > 0) {
                result = (result * 0x100000162E430E5A2) >> 64;
            }
            if (x & 0x10000000000 > 0) {
                result = (result * 0x1000000B172183551) >> 64;
            }
            if (x & 0x8000000000 > 0) {
                result = (result * 0x100000058B90C0B49) >> 64;
            }
            if (x & 0x4000000000 > 0) {
                result = (result * 0x10000002C5C8601CC) >> 64;
            }
            if (x & 0x2000000000 > 0) {
                result = (result * 0x1000000162E42FFF0) >> 64;
            }
            if (x & 0x1000000000 > 0) {
                result = (result * 0x10000000B17217FBB) >> 64;
            }
            if (x & 0x800000000 > 0) {
                result = (result * 0x1000000058B90BFCE) >> 64;
            }
            if (x & 0x400000000 > 0) {
                result = (result * 0x100000002C5C85FE3) >> 64;
            }
            if (x & 0x200000000 > 0) {
                result = (result * 0x10000000162E42FF1) >> 64;
            }
            if (x & 0x100000000 > 0) {
                result = (result * 0x100000000B17217F8) >> 64;
            }
            if (x & 0x80000000 > 0) {
                result = (result * 0x10000000058B90BFC) >> 64;
            }
            if (x & 0x40000000 > 0) {
                result = (result * 0x1000000002C5C85FE) >> 64;
            }
            if (x & 0x20000000 > 0) {
                result = (result * 0x100000000162E42FF) >> 64;
            }
            if (x & 0x10000000 > 0) {
                result = (result * 0x1000000000B17217F) >> 64;
            }
            if (x & 0x8000000 > 0) {
                result = (result * 0x100000000058B90C0) >> 64;
            }
            if (x & 0x4000000 > 0) {
                result = (result * 0x10000000002C5C860) >> 64;
            }
            if (x & 0x2000000 > 0) {
                result = (result * 0x1000000000162E430) >> 64;
            }
            if (x & 0x1000000 > 0) {
                result = (result * 0x10000000000B17218) >> 64;
            }
            if (x & 0x800000 > 0) {
                result = (result * 0x1000000000058B90C) >> 64;
            }
            if (x & 0x400000 > 0) {
                result = (result * 0x100000000002C5C86) >> 64;
            }
            if (x & 0x200000 > 0) {
                result = (result * 0x10000000000162E43) >> 64;
            }
            if (x & 0x100000 > 0) {
                result = (result * 0x100000000000B1721) >> 64;
            }
            if (x & 0x80000 > 0) {
                result = (result * 0x10000000000058B91) >> 64;
            }
            if (x & 0x40000 > 0) {
                result = (result * 0x1000000000002C5C8) >> 64;
            }
            if (x & 0x20000 > 0) {
                result = (result * 0x100000000000162E4) >> 64;
            }
            if (x & 0x10000 > 0) {
                result = (result * 0x1000000000000B172) >> 64;
            }
            if (x & 0x8000 > 0) {
                result = (result * 0x100000000000058B9) >> 64;
            }
            if (x & 0x4000 > 0) {
                result = (result * 0x10000000000002C5D) >> 64;
            }
            if (x & 0x2000 > 0) {
                result = (result * 0x1000000000000162E) >> 64;
            }
            if (x & 0x1000 > 0) {
                result = (result * 0x10000000000000B17) >> 64;
            }
            if (x & 0x800 > 0) {
                result = (result * 0x1000000000000058C) >> 64;
            }
            if (x & 0x400 > 0) {
                result = (result * 0x100000000000002C6) >> 64;
            }
            if (x & 0x200 > 0) {
                result = (result * 0x10000000000000163) >> 64;
            }
            if (x & 0x100 > 0) {
                result = (result * 0x100000000000000B1) >> 64;
            }
            if (x & 0x80 > 0) {
                result = (result * 0x10000000000000059) >> 64;
            }
            if (x & 0x40 > 0) {
                result = (result * 0x1000000000000002C) >> 64;
            }
            if (x & 0x20 > 0) {
                result = (result * 0x10000000000000016) >> 64;
            }
            if (x & 0x10 > 0) {
                result = (result * 0x1000000000000000B) >> 64;
            }
            if (x & 0x8 > 0) {
                result = (result * 0x10000000000000006) >> 64;
            }
            if (x & 0x4 > 0) {
                result = (result * 0x10000000000000003) >> 64;
            }
            if (x & 0x2 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }
            if (x & 0x1 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }

            // We're doing two things at the same time:
            //
            //   1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for
            //      the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191
            //      rather than 192.
            //   2. Convert the result to the unsigned 60.18-decimal fixed-point format.
            //
            // This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n".
            result *= SCALE;
            result >>= (191 - (x >> 64));
        }
    }

    /// @notice Finds the zero-based index of the first one in the binary representation of x.
    /// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
    /// @param x The uint256 number for which to find the index of the most significant bit.
    /// @return msb The index of the most significant bit as an uint256.
    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
        if (x >= 2**128) {
            x >>= 128;
            msb += 128;
        }
        if (x >= 2**64) {
            x >>= 64;
            msb += 64;
        }
        if (x >= 2**32) {
            x >>= 32;
            msb += 32;
        }
        if (x >= 2**16) {
            x >>= 16;
            msb += 16;
        }
        if (x >= 2**8) {
            x >>= 8;
            msb += 8;
        }
        if (x >= 2**4) {
            x >>= 4;
            msb += 4;
        }
        if (x >= 2**2) {
            x >>= 2;
            msb += 2;
        }
        if (x >= 2**1) {
            // No need to shift x any more.
            msb += 1;
        }
    }

    /// @notice Calculates floor(x*y÷denominator) with full precision.
    ///
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
    ///
    /// Requirements:
    /// - The denominator cannot be zero.
    /// - The result must fit within uint256.
    ///
    /// Caveats:
    /// - This function does not work with fixed-point numbers.
    ///
    /// @param x The multiplicand as an uint256.
    /// @param y The multiplier as an uint256.
    /// @param denominator The divisor as an uint256.
    /// @return result The result as an uint256.
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
        // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
        // variables such that product = prod1 * 2^256 + prod0.
        uint256 prod0; // Least significant 256 bits of the product
        uint256 prod1; // Most significant 256 bits of the product
        assembly {
            let mm := mulmod(x, y, not(0))
            prod0 := mul(x, y)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        // Handle non-overflow cases, 256 by 256 division.
        if (prod1 == 0) {
            unchecked {
                result = prod0 / denominator;
            }
            return result;
        }

        // Make sure the result is less than 2^256. Also prevents denominator == 0.
        if (prod1 >= denominator) {
            revert PRBMath__MulDivOverflow(prod1, denominator);
        }

        ///////////////////////////////////////////////
        // 512 by 256 division.
        ///////////////////////////////////////////////

        // Make division exact by subtracting the remainder from [prod1 prod0].
        uint256 remainder;
        assembly {
            // Compute remainder using mulmod.
            remainder := mulmod(x, y, denominator)

            // Subtract 256 bit number from 512 bit number.
            prod1 := sub(prod1, gt(remainder, prod0))
            prod0 := sub(prod0, remainder)
        }

        // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
        // See https://cs.stackexchange.com/q/138556/92363.
        unchecked {
            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 lpotdod = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by lpotdod.
                denominator := div(denominator, lpotdod)

                // Divide [prod1 prod0] by lpotdod.
                prod0 := div(prod0, lpotdod)

                // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.
                lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * lpotdod;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /// @notice Calculates floor(x*y÷1e18) with full precision.
    ///
    /// @dev Variant of "mulDiv" with constant folding, i.e. in which the denominator is always 1e18. Before returning the
    /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of
    /// being rounded to 1e-18.  See "Listing 6" and text above it at https://accu.org/index.php/journals/1717.
    ///
    /// Requirements:
    /// - The result must fit within uint256.
    ///
    /// Caveats:
    /// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works.
    /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:
    ///     1. x * y = type(uint256).max * SCALE
    ///     2. (x * y) % SCALE >= SCALE / 2
    ///
    /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
    /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
        uint256 prod0;
        uint256 prod1;
        assembly {
            let mm := mulmod(x, y, not(0))
            prod0 := mul(x, y)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        if (prod1 >= SCALE) {
            revert PRBMath__MulDivFixedPointOverflow(prod1);
        }

        uint256 remainder;
        uint256 roundUpUnit;
        assembly {
            remainder := mulmod(x, y, SCALE)
            roundUpUnit := gt(remainder, 499999999999999999)
        }

        if (prod1 == 0) {
            unchecked {
                result = (prod0 / SCALE) + roundUpUnit;
                return result;
            }
        }

        assembly {
            result := add(
                mul(
                    or(
                        div(sub(prod0, remainder), SCALE_LPOTD),
                        mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
                    ),
                    SCALE_INVERSE
                ),
                roundUpUnit
            )
        }
    }

    /// @notice Calculates floor(x*y÷denominator) with full precision.
    ///
    /// @dev An extension of "mulDiv" for signed numbers. Works by computing the signs and the absolute values separately.
    ///
    /// Requirements:
    /// - None of the inputs can be type(int256).min.
    /// - The result must fit within int256.
    ///
    /// @param x The multiplicand as an int256.
    /// @param y The multiplier as an int256.
    /// @param denominator The divisor as an int256.
    /// @return result The result as an int256.
    function mulDivSigned(
        int256 x,
        int256 y,
        int256 denominator
    ) internal pure returns (int256 result) {
        if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
            revert PRBMath__MulDivSignedInputTooSmall();
        }

        // Get hold of the absolute values of x, y and the denominator.
        uint256 ax;
        uint256 ay;
        uint256 ad;
        unchecked {
            ax = x < 0 ? uint256(-x) : uint256(x);
            ay = y < 0 ? uint256(-y) : uint256(y);
            ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
        }

        // Compute the absolute value of (x*y)÷denominator. The result must fit within int256.
        uint256 rAbs = mulDiv(ax, ay, ad);
        if (rAbs > uint256(type(int256).max)) {
            revert PRBMath__MulDivSignedOverflow(rAbs);
        }

        // Get the signs of x, y and the denominator.
        uint256 sx;
        uint256 sy;
        uint256 sd;
        assembly {
            sx := sgt(x, sub(0, 1))
            sy := sgt(y, sub(0, 1))
            sd := sgt(denominator, sub(0, 1))
        }

        // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.
        // If yes, the result should be negative.
        result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
    }

    /// @notice Calculates the square root of x, rounding down.
    /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
    ///
    /// Caveats:
    /// - This function does not work with fixed-point numbers.
    ///
    /// @param x The uint256 number for which to calculate the square root.
    /// @return result The result as an uint256.
    function sqrt(uint256 x) internal pure returns (uint256 result) {
        if (x == 0) {
            return 0;
        }

        // Set the initial guess to the closest power of two that is higher than x.
        uint256 xAux = uint256(x);
        result = 1;
        if (xAux >= 0x100000000000000000000000000000000) {
            xAux >>= 128;
            result <<= 64;
        }
        if (xAux >= 0x10000000000000000) {
            xAux >>= 64;
            result <<= 32;
        }
        if (xAux >= 0x100000000) {
            xAux >>= 32;
            result <<= 16;
        }
        if (xAux >= 0x10000) {
            xAux >>= 16;
            result <<= 8;
        }
        if (xAux >= 0x100) {
            xAux >>= 8;
            result <<= 4;
        }
        if (xAux >= 0x10) {
            xAux >>= 4;
            result <<= 2;
        }
        if (xAux >= 0x8) {
            result <<= 1;
        }

        // The operations can never overflow because the result is max 2^127 when it enters this block.
        unchecked {
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1; // Seven iterations should be enough
            uint256 roundedDownResult = x / result;
            return result >= roundedDownResult ? roundedDownResult : result;
        }
    }
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"inputs":[{"internalType":"contract IJBDirectory","name":"_directory","type":"address"},{"internalType":"contract IJBFundingCycleStore","name":"_fundingCycleStore","type":"address"},{"internalType":"contract IJBPrices","name":"_prices","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CURRENCY_MISMATCH","type":"error"},{"inputs":[],"name":"DISTRIBUTION_AMOUNT_LIMIT_REACHED","type":"error"},{"inputs":[],"name":"FUNDING_CYCLE_DISTRIBUTION_PAUSED","type":"error"},{"inputs":[],"name":"FUNDING_CYCLE_PAYMENT_PAUSED","type":"error"},{"inputs":[],"name":"FUNDING_CYCLE_REDEEM_PAUSED","type":"error"},{"inputs":[],"name":"INADEQUATE_CONTROLLER_ALLOWANCE","type":"error"},{"inputs":[],"name":"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE","type":"error"},{"inputs":[],"name":"INSUFFICIENT_TOKENS","type":"error"},{"inputs":[],"name":"INVALID_AMOUNT_TO_SEND_DELEGATE","type":"error"},{"inputs":[],"name":"INVALID_FUNDING_CYCLE","type":"error"},{"inputs":[],"name":"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED","type":"error"},{"inputs":[{"internalType":"uint256","name":"prod1","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"PRBMath__MulDivOverflow","type":"error"},{"inputs":[{"internalType":"contract IJBSingleTokenPaymentTerminal","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IJBSingleTokenPaymentTerminal","name":"_terminal","type":"address"},{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"currentOverflowOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_tokenCount","type":"uint256"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"uint256","name":"_overflow","type":"uint256"}],"name":"currentReclaimableOverflowOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IJBSingleTokenPaymentTerminal","name":"_terminal","type":"address"},{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_tokenCount","type":"uint256"},{"internalType":"bool","name":"_useTotalOverflow","type":"bool"}],"name":"currentReclaimableOverflowOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_decimals","type":"uint256"},{"internalType":"uint256","name":"_currency","type":"uint256"}],"name":"currentTotalOverflowOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"directory","outputs":[{"internalType":"contract IJBDirectory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundingCycleStore","outputs":[{"internalType":"contract IJBFundingCycleStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prices","outputs":[{"internalType":"contract IJBPrices","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recordAddedBalanceFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_currency","type":"uint256"}],"name":"recordDistributionFor","outputs":[{"components":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"configuration","type":"uint256"},{"internalType":"uint256","name":"basedOn","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint256","name":"discountRate","type":"uint256"},{"internalType":"contract IJBFundingCycleBallot","name":"ballot","type":"address"},{"internalType":"uint256","name":"metadata","type":"uint256"}],"internalType":"struct JBFundingCycle","name":"fundingCycle","type":"tuple"},{"internalType":"uint256","name":"distributedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"recordMigration","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_payer","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"uint256","name":"currency","type":"uint256"}],"internalType":"struct JBTokenAmount","name":"_amount","type":"tuple"},{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_baseWeightCurrency","type":"uint256"},{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"string","name":"_memo","type":"string"},{"internalType":"bytes","name":"_metadata","type":"bytes"}],"name":"recordPaymentFrom","outputs":[{"components":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"configuration","type":"uint256"},{"internalType":"uint256","name":"basedOn","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint256","name":"discountRate","type":"uint256"},{"internalType":"contract IJBFundingCycleBallot","name":"ballot","type":"address"},{"internalType":"uint256","name":"metadata","type":"uint256"}],"internalType":"struct JBFundingCycle","name":"fundingCycle","type":"tuple"},{"internalType":"uint256","name":"tokenCount","type":"uint256"},{"components":[{"internalType":"contract IJBPayDelegate","name":"delegate","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct JBPayDelegateAllocation[]","name":"delegateAllocations","type":"tuple[]"},{"internalType":"string","name":"memo","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"},{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_tokenCount","type":"uint256"},{"internalType":"string","name":"_memo","type":"string"},{"internalType":"bytes","name":"_metadata","type":"bytes"}],"name":"recordRedemptionFor","outputs":[{"components":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"configuration","type":"uint256"},{"internalType":"uint256","name":"basedOn","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint256","name":"discountRate","type":"uint256"},{"internalType":"contract IJBFundingCycleBallot","name":"ballot","type":"address"},{"internalType":"uint256","name":"metadata","type":"uint256"}],"internalType":"struct JBFundingCycle","name":"fundingCycle","type":"tuple"},{"internalType":"uint256","name":"reclaimAmount","type":"uint256"},{"components":[{"internalType":"contract IJBRedemptionDelegate","name":"delegate","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct JBRedemptionDelegateAllocation[]","name":"delegateAllocations","type":"tuple[]"},{"internalType":"string","name":"memo","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_currency","type":"uint256"}],"name":"recordUsedAllowanceOf","outputs":[{"components":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"configuration","type":"uint256"},{"internalType":"uint256","name":"basedOn","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint256","name":"discountRate","type":"uint256"},{"internalType":"contract IJBFundingCycleBallot","name":"ballot","type":"address"},{"internalType":"uint256","name":"metadata","type":"uint256"}],"internalType":"struct JBFundingCycle","name":"fundingCycle","type":"tuple"},{"internalType":"uint256","name":"usedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IJBSingleTokenPaymentTerminal","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"usedDistributionLimitOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IJBSingleTokenPaymentTerminal","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"usedOverflowAllowanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60e06040523480156200001157600080fd5b5060405162003b6838038062003b68833981016040819052620000349162000070565b60016000556001600160a01b0392831660805290821660a0521660c052620000c4565b6001600160a01b03811681146200006d57600080fd5b50565b6000806000606084860312156200008657600080fd5b8351620000938162000057565b6020850151909350620000a68162000057565b6040850151909250620000b98162000057565b809150509250925092565b60805160a05160c0516139e862000180600039600081816102630152818161079101528181610e0b015281816126ac01526128bb01526000818161018b0152818161040e015281816109ca01528181610f580152818161113a015281816115ab015281816118a70152818161198901528181611dc201528181612201015261295b015260008181610229015281816104be0152818161139301528181611b8401528181611eb401528181612494015261274101526139e86000f3fe608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612b19565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612b45565b61030f565b604051610139929190612b71565b610176610171366004612d68565b6108cd565b6040516101399493929190612e79565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004612f56565b610eb4565b6101766101e6366004612f6f565b61103d565b61012f6101f9366004613010565b611853565b61012f61020c366004612b45565b611936565b61012f61021f366004613042565b61194d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b610155610259366004612b45565b611cc8565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f610293366004612b19565b6121f8565b61012f6102a6366004613091565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d73660046130c6565b6122d6565b005b61012f6102ec366004613091565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906130f8565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b79086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b91906131ba565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c291906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610633573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065791906131d7565b9150915081831180610667575081155b1561069e576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146106d7576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b91906131fb565b905080871461080f5761080a886107546012600a613334565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080591906131fb565b61231f565b610811565b875b945061081f338a8884612423565b851115610858576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c83529052205461089c908690613340565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109256040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403610996576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906130f8565b8051909450600003610a7c576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610ac1576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610af757506000610aeb86610100015160541c90565b6001600160a01b031614155b15610c49576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b399190613353565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610bca86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610bf591906133c2565b6000604051808303816000875af1158015610c14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3c9190810190613530565b955093509150610c8a9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d1f5760005b8451811015610d1d576000858281518110610cb757610cb7613621565b602002602001015160200151905080600014610d145782811115610d07576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d118184613340565b92505b50600101610c9a565b505b8c60200135600003610d37575060009350610e9d9050565b8015610d9e573360009081526001602090815260408083208f8452909152902054610d639082906131a7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610db1575060009250610e9d565b60408c0135600060608e01358c14610e7b576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906131fb565b610e86565b610e8682600a613334565b9050610e978e60200135848361231f565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc91906130f8565b610100810151909150604d1c600190811614611014576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110956040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906130f8565b610100810151909450604a1c6001908116036111f6576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61122a604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129191906131ba565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906131fb565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611339573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135d91906131fb565b6101008b015190915060511c6001908116146113845761137f338f8c84612423565b61138f565b61138f8e8383612705565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016113df91815260200190565b602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142091906131ba565b6001600160a01b031663b5f1e34d8f6114458d610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa15801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c291906131fb565b9350838d11156114fe576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415611514576115118e8b8f8789612919565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115745750600061156888610100015160541c90565b6001600160a01b031614155b15611764576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190613650565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d815260200184815260200185815260200186815260200161168b8b6101000151600160519190911c81161490565b1515815260200160008460028111156116a6576116a6613671565b146116b9576116b48b612a6a565b6116c2565b6116c28b612a87565b81526020018c81526020018b81525090506116e289610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161170d91906136a0565b6000604051808303816000875af115801561172c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611754919081019061379b565b9199509097509550611768915050565b8893505b50508251849150156117c25760005b83518110156117c057600084828151811061179457611794613621565b6020026020010151602001519050806000146117b7576117b481846131a7565b92505b50600101611777565b505b3360009081526001602090815260408083208c8452909152902054811115611816576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561183e573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118655750600061192e565b828411156118755750600061192e565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906130f8565b905061192a8682878787612919565b9150505b949350505050565b6000611943848484612705565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f591906130f8565b9050600083611a7057611a6b8787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6691906131fb565b612423565b611b3d565b611b3d86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad691906131fb565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3891906131fb565b612705565b905080600003611b525760009250505061192e565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf791906131ba565b6001600160a01b031663b5f1e34d88611c1c86610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9991906131fb565b905080861115611caf576000935050505061192e565b611cbc8784888486612919565b98975050505050505050565b611d206040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906130f8565b61010081015190925060491c600190811603611e7e576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ead9086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611f0091815260200190565b602060405180830381865afa158015611f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4191906131ba565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb891906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204d91906131d7565b915091508183118061205d575081155b15612094576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146120cd576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213191906131fb565b905080871461214f5761214a886107546012600a613334565b612151565b875b3360009081526001602090815260408083208d84529091529020549095508511156121a8576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b60006122cd83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b815260040161224d91815260200190565b61012060405180830381865afa15801561226b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228f91906130f8565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b90505b92915050565b3360009081526001602090815260408083208584529091529020546122fc9082906131a7565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123775783828161236d5761236d61387c565b0492505050611946565b8381106123ba576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b038416600090815260016020908152604080832086845290915281205480820361245857600091505061192e565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa1580156124db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ff91906131ba565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612552573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257691906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156125e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260b91906131d7565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906126499084613340565b9050801580159061265a5750858214155b156126e6576126e38161266f6012600a613334565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064016107c4565b90505b8084116126f45760006126f8565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa158015612788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127b091908101906138ab565b90506000805b825181101561285b578281815181106127d1576127d1613621565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161280691815260200190565b602060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284791906131fb565b61285190836131a7565b91506001016127b6565b506000600185146128ef576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526128ea908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf2906064016107c4565b6128f1565b815b90508560121461290c5761290781601288612aa4565b61290e565b805b979650505050505050565b6000828403612929575080612a61565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce9190613650565b60028111156129df576129df613671565b146129f2576129ed86612a6a565b6129fb565b6129fb86612a87565b905080600003612a0f576000915050612a61565b6000612a1c84878761231f565b90506127108203612a30579150612a619050565b612a5c81612a4a88612a4486612710613340565b8961231f565b612a5490856131a7565b61271061231f565b925050505b95945050505050565b60006028826101000151901c61ffff166127106122d09190613340565b60006038826101000151901c61ffff166127106122d09190613340565b6000828203612ab4575082611946565b82821115612ae257612ac68383613340565b612ad190600a613334565b612adb908561393a565b9050611946565b612aec8284613340565b612af790600a613334565b612adb9085613977565b6001600160a01b0381168114612b1657600080fd5b50565b60008060408385031215612b2c57600080fd5b8235612b3781612b01565b946020939093013593505050565b600080600060608486031215612b5a57600080fd5b505081359360208301359350604090920135919050565b6101408101612bde8285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612bfe57600080fd5b50813567ffffffffffffffff811115612c1657600080fd5b602083019150836020828501011115612c2e57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c8857612c88612c35565b60405290565b6040805190810167ffffffffffffffff81118282101715612c8857612c88612c35565b604051601f8201601f1916810167ffffffffffffffff81118282101715612cda57612cda612c35565b604052919050565b600067ffffffffffffffff821115612cfc57612cfc612c35565b50601f01601f191660200190565b6000612d1d612d1884612ce2565b612cb1565b9050828152838383011115612d3157600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5957600080fd5b6122cd83833560208501612d0a565b600080600080600080600080888a03610140811215612d8657600080fd5b8935612d9181612b01565b98506080601f1982011215612da557600080fd5b5060208901965060a0890135955060c0890135945060e0890135612dc881612b01565b935061010089013567ffffffffffffffff80821115612de657600080fd5b612df28c838d01612bec565b90955093506101208b0135915080821115612e0c57600080fd5b50612e198b828c01612d48565b9150509295985092959890939650565b60005b83811015612e44578181015183820152602001612e2c565b50506000910152565b60008151808452612e65816020860160208601612e29565b601f01601f19169290920160200192915050565b6000610180808301612ee98489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612f3f57815180516001600160a01b031686528401518486015260409094019390830190600101612f0f565b5050505082810361016084015261290e8185612e4d565b600060208284031215612f6857600080fd5b5035919050565b600080600080600060a08688031215612f8757600080fd5b8535612f9281612b01565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612fbd57600080fd5b818801915088601f830112612fd157600080fd5b612fe089833560208501612d0a565b93506080880135915080821115612ff657600080fd5b5061300388828901612d48565b9150509295509295909350565b6000806000806080858703121561302657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561305857600080fd5b843561306381612b01565b935060208501359250604085013591506060850135801515811461308657600080fd5b939692955090935050565b6000806000606084860312156130a657600080fd5b83356130b181612b01565b95602085013595506040909401359392505050565b600080604083850312156130d957600080fd5b50508035926020909101359150565b80516130f381612b01565b919050565b6000610120828403121561310b57600080fd5b613113612c64565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261315f60e084016130e8565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156122d0576122d0613178565b6000602082840312156131cc57600080fd5b815161194681612b01565b600080604083850312156131ea57600080fd5b505080516020909101519092909150565b60006020828403121561320d57600080fd5b5051919050565b600181815b8085111561326d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561325357613253613178565b8085161561326057918102915b93841c9390800290613219565b509250929050565b600082613284575060016122d0565b81613291575060006122d0565b81600181146132a757600281146132b1576132cd565b60019150506122d0565b60ff8411156132c2576132c2613178565b50506001821b6122d0565b5060208310610133831016604e8410600b84101617156132f0575081810a6122d0565b6132fa8383613214565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561332c5761332c613178565b029392505050565b60006122cd8383613275565b818103818111156122d0576122d0613178565b60006080828403121561336557600080fd5b6040516080810181811067ffffffffffffffff8211171561338857613388612c35565b604052823561339681612b01565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526133dc6020820183516001600160a01b03169052565b600060208301516133f860408401826001600160a01b03169052565b50604083015161343560608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a0850151915061012061346b818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a09150816101808601526134a16101c0860184612e4d565b90860151858203601f1901838701529092506134bd8382612e4d565b9695505050505050565b600082601f8301126134d857600080fd5b81516134e6612d1882612ce2565b8181528460208386010111156134fb57600080fd5b61192e826020830160208701612e29565b600067ffffffffffffffff82111561352657613526612c35565b5060051b60200190565b60008060006060848603121561354557600080fd5b8351925060208085015167ffffffffffffffff8082111561356557600080fd5b613571888389016134c7565b945060409150818701518181111561358857600080fd5b87019050601f8101881361359b57600080fd5b80516135a9612d188261350c565b81815260069190911b8201840190848101908a8311156135c857600080fd5b928501925b828410156136115784848c0312156135e55760008081fd5b6135ed612c8e565b84516135f881612b01565b81528487015187820152825292840192908501906135cd565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561366257600080fd5b81516003811061194657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526136ba6020820183516001600160a01b03169052565b600060208301516136d660408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613747818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c0840181905261377e610200850183612e4d565b9150610160850151601f1985840301828601526134bd8382612e4d565b6000806000606084860312156137b057600080fd5b8351925060208085015167ffffffffffffffff808211156137d057600080fd5b6137dc888389016134c7565b94506040915081870151818111156137f357600080fd5b87019050601f8101881361380657600080fd5b8051613814612d188261350c565b81815260069190911b8201840190848101908a83111561383357600080fd5b928501925b828410156136115784848c0312156138505760008081fd5b613858612c8e565b845161386381612b01565b8152848701518782015282529284019290850190613838565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060208083850312156138be57600080fd5b825167ffffffffffffffff8111156138d557600080fd5b8301601f810185136138e657600080fd5b80516138f4612d188261350c565b81815260059190911b8201830190838101908783111561391357600080fd5b928401925b8284101561290e57835161392b81612b01565b82529284019290840190613918565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397257613972613178565b500290565b6000826139ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220496c9f50e79f6514ca61a35b21fe271a2d4fe217f051df7336af8ae92911191e64736f6c634300081000330000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a99000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b550000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612b19565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612b45565b61030f565b604051610139929190612b71565b610176610171366004612d68565b6108cd565b6040516101399493929190612e79565b6101ad7f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b5581565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004612f56565b610eb4565b6101766101e6366004612f6f565b61103d565b61012f6101f9366004613010565b611853565b61012f61020c366004612b45565b611936565b61012f61021f366004613042565b61194d565b6101ad7f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a9981565b610155610259366004612b45565b611cc8565b6101ad7f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c81565b61012f610293366004612b19565b6121f8565b61012f6102a6366004613091565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d73660046130c6565b6122d6565b005b61012f6102ec366004613091565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906130f8565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b79086906131a7565b90506000807f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b91906131ba565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c291906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610633573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065791906131d7565b9150915081831180610667575081155b1561069e576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146106d7576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b91906131fb565b905080871461080f5761080a886107546012600a613334565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c6001600160a01b03169063a4d0caf2906064015b602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080591906131fb565b61231f565b610811565b875b945061081f338a8884612423565b851115610858576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c83529052205461089c908690613340565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109256040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403610996576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906130f8565b8051909450600003610a7c576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610ac1576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610af757506000610aeb86610100015160541c90565b6001600160a01b031614155b15610c49576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b399190613353565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610bca86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610bf591906133c2565b6000604051808303816000875af1158015610c14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3c9190810190613530565b955093509150610c8a9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d1f5760005b8451811015610d1d576000858281518110610cb757610cb7613621565b602002602001015160200151905080600014610d145782811115610d07576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d118184613340565b92505b50600101610c9a565b505b8c60200135600003610d37575060009350610e9d9050565b8015610d9e573360009081526001602090815260408083208f8452909152902054610d639082906131a7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610db1575060009250610e9d565b60408c0135600060608e01358c14610e7b576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c169063a4d0caf290606401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906131fb565b610e86565b610e8682600a613334565b9050610e978e60200135848361231f565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc91906130f8565b610100810151909150604d1c600190811614611014576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110956040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906130f8565b610100810151909450604a1c6001908116036111f6576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61122a604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129191906131ba565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906131fb565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611339573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135d91906131fb565b6101008b015190915060511c6001908116146113845761137f338f8c84612423565b61138f565b61138f8e8383612705565b94507f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016113df91815260200190565b602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142091906131ba565b6001600160a01b031663b5f1e34d8f6114458d610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa15801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c291906131fb565b9350838d11156114fe576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415611514576115118e8b8f8789612919565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115745750600061156888610100015160541c90565b6001600160a01b031614155b15611764576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b03169063c55f571c90602401602060405180830381865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190613650565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d815260200184815260200185815260200186815260200161168b8b6101000151600160519190911c81161490565b1515815260200160008460028111156116a6576116a6613671565b146116b9576116b48b612a6a565b6116c2565b6116c28b612a87565b81526020018c81526020018b81525090506116e289610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161170d91906136a0565b6000604051808303816000875af115801561172c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611754919081019061379b565b9199509097509550611768915050565b8893505b50508251849150156117c25760005b83518110156117c057600084828151811061179457611794613621565b6020026020010151602001519050806000146117b7576117b481846131a7565b92505b50600101611777565b505b3360009081526001602090815260408083208c8452909152902054811115611816576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561183e573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118655750600061192e565b828411156118755750600061192e565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906130f8565b905061192a8682878787612919565b9150505b949350505050565b6000611943848484612705565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b5516906343a266c29060240161012060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f591906130f8565b9050600083611a7057611a6b8787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6691906131fb565b612423565b611b3d565b611b3d86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad691906131fb565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3891906131fb565b612705565b905080600003611b525760009250505061192e565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf791906131ba565b6001600160a01b031663b5f1e34d88611c1c86610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9991906131fb565b905080861115611caf576000935050505061192e565b611cbc8784888486612919565b98975050505050505050565b611d206040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906130f8565b61010081015190925060491c600190811603611e7e576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ead9086906131a7565b90506000807f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611f0091815260200190565b602060405180830381865afa158015611f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4191906131ba565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb891906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204d91906131d7565b915091508183118061205d575081155b15612094576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146120cd576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213191906131fb565b905080871461214f5761214a886107546012600a613334565b612151565b875b3360009081526001602090815260408083208d84529091529020549095508511156121a8576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b60006122cd83837f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b03166343a266c2866040518263ffffffff1660e01b815260040161224d91815260200190565b61012060405180830381865afa15801561226b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228f91906130f8565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b90505b92915050565b3360009081526001602090815260408083208584529091529020546122fc9082906131a7565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123775783828161236d5761236d61387c565b0492505050611946565b8381106123ba576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b038416600090815260016020908152604080832086845290915281205480820361245857600091505061192e565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a991690635dd8f6aa90602401602060405180830381865afa1580156124db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ff91906131ba565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612552573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257691906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156125e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260b91906131d7565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906126499084613340565b9050801580159061265a5750858214155b156126e6576126e38161266f6012600a613334565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c6001600160a01b03169063a4d0caf2906064016107c4565b90505b8084116126f45760006126f8565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a99169063d175415390602401600060405180830381865afa158015612788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127b091908101906138ab565b90506000805b825181101561285b578281815181106127d1576127d1613621565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161280691815260200190565b602060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284791906131fb565b61285190836131a7565b91506001016127b6565b506000600185146128ef576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526128ea908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c169063a4d0caf2906064016107c4565b6128f1565b815b90508560121461290c5761290781601288612aa4565b61290e565b805b979650505050505050565b6000828403612929575080612a61565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b03169063c55f571c90602401602060405180830381865afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce9190613650565b60028111156129df576129df613671565b146129f2576129ed86612a6a565b6129fb565b6129fb86612a87565b905080600003612a0f576000915050612a61565b6000612a1c84878761231f565b90506127108203612a30579150612a619050565b612a5c81612a4a88612a4486612710613340565b8961231f565b612a5490856131a7565b61271061231f565b925050505b95945050505050565b60006028826101000151901c61ffff166127106122d09190613340565b60006038826101000151901c61ffff166127106122d09190613340565b6000828203612ab4575082611946565b82821115612ae257612ac68383613340565b612ad190600a613334565b612adb908561393a565b9050611946565b612aec8284613340565b612af790600a613334565b612adb9085613977565b6001600160a01b0381168114612b1657600080fd5b50565b60008060408385031215612b2c57600080fd5b8235612b3781612b01565b946020939093013593505050565b600080600060608486031215612b5a57600080fd5b505081359360208301359350604090920135919050565b6101408101612bde8285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612bfe57600080fd5b50813567ffffffffffffffff811115612c1657600080fd5b602083019150836020828501011115612c2e57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c8857612c88612c35565b60405290565b6040805190810167ffffffffffffffff81118282101715612c8857612c88612c35565b604051601f8201601f1916810167ffffffffffffffff81118282101715612cda57612cda612c35565b604052919050565b600067ffffffffffffffff821115612cfc57612cfc612c35565b50601f01601f191660200190565b6000612d1d612d1884612ce2565b612cb1565b9050828152838383011115612d3157600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5957600080fd5b6122cd83833560208501612d0a565b600080600080600080600080888a03610140811215612d8657600080fd5b8935612d9181612b01565b98506080601f1982011215612da557600080fd5b5060208901965060a0890135955060c0890135945060e0890135612dc881612b01565b935061010089013567ffffffffffffffff80821115612de657600080fd5b612df28c838d01612bec565b90955093506101208b0135915080821115612e0c57600080fd5b50612e198b828c01612d48565b9150509295985092959890939650565b60005b83811015612e44578181015183820152602001612e2c565b50506000910152565b60008151808452612e65816020860160208601612e29565b601f01601f19169290920160200192915050565b6000610180808301612ee98489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612f3f57815180516001600160a01b031686528401518486015260409094019390830190600101612f0f565b5050505082810361016084015261290e8185612e4d565b600060208284031215612f6857600080fd5b5035919050565b600080600080600060a08688031215612f8757600080fd5b8535612f9281612b01565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612fbd57600080fd5b818801915088601f830112612fd157600080fd5b612fe089833560208501612d0a565b93506080880135915080821115612ff657600080fd5b5061300388828901612d48565b9150509295509295909350565b6000806000806080858703121561302657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561305857600080fd5b843561306381612b01565b935060208501359250604085013591506060850135801515811461308657600080fd5b939692955090935050565b6000806000606084860312156130a657600080fd5b83356130b181612b01565b95602085013595506040909401359392505050565b600080604083850312156130d957600080fd5b50508035926020909101359150565b80516130f381612b01565b919050565b6000610120828403121561310b57600080fd5b613113612c64565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261315f60e084016130e8565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156122d0576122d0613178565b6000602082840312156131cc57600080fd5b815161194681612b01565b600080604083850312156131ea57600080fd5b505080516020909101519092909150565b60006020828403121561320d57600080fd5b5051919050565b600181815b8085111561326d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561325357613253613178565b8085161561326057918102915b93841c9390800290613219565b509250929050565b600082613284575060016122d0565b81613291575060006122d0565b81600181146132a757600281146132b1576132cd565b60019150506122d0565b60ff8411156132c2576132c2613178565b50506001821b6122d0565b5060208310610133831016604e8410600b84101617156132f0575081810a6122d0565b6132fa8383613214565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561332c5761332c613178565b029392505050565b60006122cd8383613275565b818103818111156122d0576122d0613178565b60006080828403121561336557600080fd5b6040516080810181811067ffffffffffffffff8211171561338857613388612c35565b604052823561339681612b01565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526133dc6020820183516001600160a01b03169052565b600060208301516133f860408401826001600160a01b03169052565b50604083015161343560608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a0850151915061012061346b818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a09150816101808601526134a16101c0860184612e4d565b90860151858203601f1901838701529092506134bd8382612e4d565b9695505050505050565b600082601f8301126134d857600080fd5b81516134e6612d1882612ce2565b8181528460208386010111156134fb57600080fd5b61192e826020830160208701612e29565b600067ffffffffffffffff82111561352657613526612c35565b5060051b60200190565b60008060006060848603121561354557600080fd5b8351925060208085015167ffffffffffffffff8082111561356557600080fd5b613571888389016134c7565b945060409150818701518181111561358857600080fd5b87019050601f8101881361359b57600080fd5b80516135a9612d188261350c565b81815260069190911b8201840190848101908a8311156135c857600080fd5b928501925b828410156136115784848c0312156135e55760008081fd5b6135ed612c8e565b84516135f881612b01565b81528487015187820152825292840192908501906135cd565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561366257600080fd5b81516003811061194657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526136ba6020820183516001600160a01b03169052565b600060208301516136d660408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613747818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c0840181905261377e610200850183612e4d565b9150610160850151601f1985840301828601526134bd8382612e4d565b6000806000606084860312156137b057600080fd5b8351925060208085015167ffffffffffffffff808211156137d057600080fd5b6137dc888389016134c7565b94506040915081870151818111156137f357600080fd5b87019050601f8101881361380657600080fd5b8051613814612d188261350c565b81815260069190911b8201840190848101908a83111561383357600080fd5b928501925b828410156136115784848c0312156138505760008081fd5b613858612c8e565b845161386381612b01565b8152848701518782015282529284019290850190613838565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060208083850312156138be57600080fd5b825167ffffffffffffffff8111156138d557600080fd5b8301601f810185136138e657600080fd5b80516138f4612d188261350c565b81815260059190911b8201830190838101908783111561391357600080fd5b928401925b8284101561290e57835161392b81612b01565b82529284019290840190613918565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397257613972613178565b500290565b6000826139ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220496c9f50e79f6514ca61a35b21fe271a2d4fe217f051df7336af8ae92911191e64736f6c63430008100033

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

0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a99000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b550000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c

-----Decoded View---------------
Arg [0] : _directory (address): 0x8E05bcD2812E1449f0EC3aE24E2C395F533d9A99
Arg [1] : _fundingCycleStore (address): 0xB9Ee9d8203467f6EC0eAC81163d210bd1a7d3b55
Arg [2] : _prices (address): 0x9f0eC91d28fFc54874e9fF11A316Ba2537aCD72C

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a99
Arg [1] : 000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b55
Arg [2] : 0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
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.