Goerli Testnet

Contract

0x5d8eC74256DB2326843714B852df3acE45144492

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Value
0x60e0604092666382023-06-30 14:18:36247 days ago1688134716IN
 Create: JBSingleTokenPaymentTerminalStore3_1_1
0 ETH0.004500071.50033769

Latest 25 internal transactions (View All)

Advanced mode:
Parent Txn Hash Block From To Value
104613702024-01-31 9:02:0032 days ago1706691720
0x5d8eC742...E45144492
0 ETH
104613702024-01-31 9:02:0032 days ago1706691720
0x5d8eC742...E45144492
0 ETH
104613582024-01-31 8:59:1232 days ago1706691552
0x5d8eC742...E45144492
0 ETH
104613582024-01-31 8:59:1232 days ago1706691552
0x5d8eC742...E45144492
0 ETH
104501002024-01-29 6:04:2434 days ago1706508264
0x5d8eC742...E45144492
0 ETH
104501002024-01-29 6:04:2434 days ago1706508264
0x5d8eC742...E45144492
0 ETH
104501002024-01-29 6:04:2434 days ago1706508264
0x5d8eC742...E45144492
0 ETH
104335942024-01-25 22:28:4838 days ago1706221728
0x5d8eC742...E45144492
0 ETH
104335942024-01-25 22:28:4838 days ago1706221728
0x5d8eC742...E45144492
0 ETH
104335942024-01-25 22:28:4838 days ago1706221728
0x5d8eC742...E45144492
0 ETH
104335842024-01-25 22:26:3638 days ago1706221596
0x5d8eC742...E45144492
0 ETH
104335842024-01-25 22:26:3638 days ago1706221596
0x5d8eC742...E45144492
0 ETH
104335842024-01-25 22:26:3638 days ago1706221596
0x5d8eC742...E45144492
0 ETH
104335712024-01-25 22:22:3638 days ago1706221356
0x5d8eC742...E45144492
0 ETH
104335712024-01-25 22:22:3638 days ago1706221356
0x5d8eC742...E45144492
0 ETH
104335712024-01-25 22:22:3638 days ago1706221356
0x5d8eC742...E45144492
0 ETH
104332112024-01-25 20:44:0038 days ago1706215440
0x5d8eC742...E45144492
0 ETH
104332112024-01-25 20:44:0038 days ago1706215440
0x5d8eC742...E45144492
0 ETH
104332112024-01-25 20:44:0038 days ago1706215440
0x5d8eC742...E45144492
0 ETH
104322632024-01-25 16:28:2438 days ago1706200104
0x5d8eC742...E45144492
0 ETH
104322632024-01-25 16:28:2438 days ago1706200104
0x5d8eC742...E45144492
0 ETH
104302452024-01-25 7:30:4838 days ago1706167848
0x5d8eC742...E45144492
0 ETH
104302452024-01-25 7:30:4838 days ago1706167848
0x5d8eC742...E45144492
0 ETH
104302452024-01-25 7:30:4838 days ago1706167848
0x5d8eC742...E45144492
0 ETH
104302062024-01-25 7:19:0038 days ago1706167140
0x5d8eC742...E45144492
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
JBSingleTokenPaymentTerminalStore3_1_1

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 49 : JBSingleTokenPaymentTerminalStore3_1_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {ReentrancyGuard} from '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import {PRBMath} from '@paulrberg/contracts/math/PRBMath.sol';
import {JBBallotState} from './enums/JBBallotState.sol';
import {IJBController3_1} from './interfaces/IJBController3_1.sol';
import {IJBDirectory} from './interfaces/IJBDirectory.sol';
import {IJBFundingCycleDataSource3_1_1} from './interfaces/IJBFundingCycleDataSource3_1_1.sol';
import {IJBFundingCycleStore} from './interfaces/IJBFundingCycleStore.sol';
import {IJBPaymentTerminal} from './interfaces/IJBPaymentTerminal.sol';
import {IJBPrices} from './interfaces/IJBPrices.sol';
import {IJBSingleTokenPaymentTerminal} from './interfaces/IJBSingleTokenPaymentTerminal.sol';
import {IJBSingleTokenPaymentTerminalStore3_1_1} from './interfaces/IJBSingleTokenPaymentTerminalStore3_1_1.sol';
import {JBConstants} from './libraries/JBConstants.sol';
import {JBCurrencies} from './libraries/JBCurrencies.sol';
import {JBFixedPointNumber} from './libraries/JBFixedPointNumber.sol';
import {JBFundingCycleMetadataResolver} from './libraries/JBFundingCycleMetadataResolver.sol';
import {JBFundingCycle} from './structs/JBFundingCycle.sol';
import {JBPayDelegateAllocation3_1_1} from './structs/JBPayDelegateAllocation3_1_1.sol';
import {JBPayParamsData} from './structs/JBPayParamsData.sol';
import {JBRedeemParamsData} from './structs/JBRedeemParamsData.sol';
import {JBRedemptionDelegateAllocation3_1_1} from './structs/JBRedemptionDelegateAllocation3_1_1.sol';
import {JBTokenAmount} from './structs/JBTokenAmount.sol';

/// @notice Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.
/// @dev This Store expects a project's controller to be an IJBController3_1.
contract JBSingleTokenPaymentTerminalStore3_1_1 is
  ReentrancyGuard,
  IJBSingleTokenPaymentTerminalStore3_1_1
{
  // 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 balance is represented as a fixed point number with the same amount of decimals as its relative terminal.
  /// @custom:param _terminal The terminal to which the balance applies.
  /// @custom:param _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.
  /// @custom:param _terminal The terminal to which the used distribution limit applies.
  /// @custom:param _projectId The ID of the project to get the used distribution limit of.
  /// @custom:param _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.
  /// @custom:param _terminal The terminal to which the overflow allowance applies.
  /// @custom:param _projectId The ID of the project to get the used overflow allowance of.
  /// @custom:param _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 = IJBController3_1(directory.controllerOf(_projectId))
      .totalOutstandingTokensOf(_projectId);

    // 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,
      JBPayDelegateAllocation3_1_1[] 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) = IJBFundingCycleDataSource3_1_1(
        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,
      JBRedemptionDelegateAllocation3_1_1[] 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 = IJBController3_1(directory.controllerOf(_projectId))
          .totalOutstandingTokensOf(_projectId);

        // 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) = IJBFundingCycleDataSource3_1_1(
            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) = IJBController3_1(
      directory.controllerOf(_projectId)
    ).fundAccessConstraintsStore().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) = IJBController3_1(
      directory.controllerOf(_projectId)
    ).fundAccessConstraintsStore().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) = IJBController3_1(
      directory.controllerOf(_projectId)
    ).fundAccessConstraintsStore().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 49 : 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 49 : PRBMath.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;

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

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

enum JBBallotState {
  Active,
  Approved,
  Failed
}

File 5 of 49 : IJBController3_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import {JBBallotState} from './../enums/JBBallotState.sol';
import {JBFundAccessConstraints} from './../structs/JBFundAccessConstraints.sol';
import {JBFundingCycle} from './../structs/JBFundingCycle.sol';
import {JBFundingCycleData} from './../structs/JBFundingCycleData.sol';
import {JBFundingCycleMetadata} from './../structs/JBFundingCycleMetadata.sol';
import {JBGroupedSplits} from './../structs/JBGroupedSplits.sol';
import {JBProjectMetadata} from './../structs/JBProjectMetadata.sol';
import {JBSplit} from './../structs/JBSplit.sol';
import {IJBController3_0_1} from './IJBController3_0_1.sol';
import {IJBDirectory} from './IJBDirectory.sol';
import {IJBFundAccessConstraintsStore} from './IJBFundAccessConstraintsStore.sol';
import {IJBFundingCycleStore} from './IJBFundingCycleStore.sol';
import {IJBMigratable} from './IJBMigratable.sol';
import {IJBPaymentTerminal} from './IJBPaymentTerminal.sol';
import {IJBProjects} from './IJBProjects.sol';
import {IJBSplitsStore} from './IJBSplitsStore.sol';
import {IJBTokenStore} from './IJBTokenStore.sol';

interface IJBController3_1 is IJBController3_0_1, 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 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 fundAccessConstraintsStore() external view returns (IJBFundAccessConstraintsStore);

  function directory() external view returns (IJBDirectory);

  function reservedTokenBalanceOf(uint256 projectId) external view returns (uint256);

  function totalOutstandingTokensOf(uint256 projectId) 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 6 of 49 : IJBDirectory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBFundingCycleStore} from './IJBFundingCycleStore.sol';
import {IJBPaymentTerminal} from './IJBPaymentTerminal.sol';
import {IJBProjects} from './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 account) 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 account, bool flag) external;
}

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

import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import {JBPayDelegateAllocation3_1_1} from './../structs/JBPayDelegateAllocation3_1_1.sol';
import {JBPayParamsData} from './../structs/JBPayParamsData.sol';
import {JBRedeemParamsData} from './../structs/JBRedeemParamsData.sol';
import {JBRedemptionDelegateAllocation3_1_1} from './../structs/JBRedemptionDelegateAllocation3_1_1.sol';

/// @title Datasource
/// @notice The datasource is called by JBPayoutRedemptionPaymentTerminals 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
interface IJBFundingCycleDataSource3_1_1 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:
  /// @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,
      JBPayDelegateAllocation3_1_1[] 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:
  /// @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,
      JBRedemptionDelegateAllocation3_1_1[] memory delegateAllocations
    );
}

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

import {JBBallotState} from './../enums/JBBallotState.sol';
import {JBFundingCycle} from './../structs/JBFundingCycle.sol';
import {JBFundingCycleData} from './../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 9 of 49 : IJBPaymentTerminal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from '@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 10 of 49 : IJBPrices.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBPriceFeed} from './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 11 of 49 : IJBSingleTokenPaymentTerminal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBPaymentTerminal} from './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 12 of 49 : IJBSingleTokenPaymentTerminalStore3_1_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBFundingCycle} from './../structs/JBFundingCycle.sol';
import {JBPayDelegateAllocation3_1_1} from './../structs/JBPayDelegateAllocation3_1_1.sol';
import {JBRedemptionDelegateAllocation3_1_1} from './../structs/JBRedemptionDelegateAllocation3_1_1.sol';
import {JBTokenAmount} from './../structs/JBTokenAmount.sol';
import {IJBDirectory} from './IJBDirectory.sol';
import {IJBFundingCycleStore} from './IJBFundingCycleStore.sol';
import {IJBPrices} from './IJBPrices.sol';
import {IJBSingleTokenPaymentTerminal} from './IJBSingleTokenPaymentTerminal.sol';

interface IJBSingleTokenPaymentTerminalStore3_1_1 {
  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 inputMemo,
    bytes calldata metadata
  )
    external
    returns (
      JBFundingCycle memory fundingCycle,
      uint256 tokenCount,
      JBPayDelegateAllocation3_1_1[] memory delegateAllocations,
      string memory outputMemo
    );

  function recordRedemptionFor(
    address holder,
    uint256 projectId,
    uint256 tokenCount,
    string calldata inputMemo,
    bytes calldata metadata
  )
    external
    returns (
      JBFundingCycle memory fundingCycle,
      uint256 reclaimAmount,
      JBRedemptionDelegateAllocation3_1_1[] memory delegateAllocations,
      string memory outputMemo
    );

  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 13 of 49 : 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 14 of 49 : JBCurrencies.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

File 15 of 49 : 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 16 of 49 : JBFundingCycleMetadataResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {JBFundingCycle} from './../structs/JBFundingCycle.sol';
import {JBFundingCycleMetadata} from './../structs/JBFundingCycleMetadata.sol';
import {JBGlobalFundingCycleMetadata} from './../structs/JBGlobalFundingCycleMetadata.sol';
import {JBConstants} from './JBConstants.sol';
import {JBGlobalFundingCycleMetadataResolver} from './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 17 of 49 : JBFundingCycle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBFundingCycleBallot} from './../interfaces/IJBFundingCycleBallot.sol';

/// @custom: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.
/// @custom: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.
/// @custom:member basedOn The `configuration` of the funding cycle that was active when this cycle was created.
/// @custom:member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.
/// @custom: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`.
/// @custom: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.
/// @custom: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`.
/// @custom: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.
/// @custom: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 18 of 49 : JBPayDelegateAllocation3_1_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBPayDelegate3_1_1} from '../interfaces/IJBPayDelegate3_1_1.sol';

/// @custom:member delegate A delegate contract to use for subsequent calls.
/// @custom:member amount The amount to send to the delegate.
/// @custom:member metadata Metadata to pass the delegate.
struct JBPayDelegateAllocation3_1_1 {
  IJBPayDelegate3_1_1 delegate;
  uint256 amount;
  bytes metadata;
}

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

import {IJBPaymentTerminal} from './../interfaces/IJBPaymentTerminal.sol';
import {JBTokenAmount} from './JBTokenAmount.sol';

/// @custom:member terminal The terminal that is facilitating the payment.
/// @custom:member payer The address from which the payment originated.
/// @custom: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.
/// @custom:member projectId The ID of the project being paid.
/// @custom:member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.
/// @custom:member beneficiary The specified address that should be the beneficiary of anything that results from the payment.
/// @custom:member weight The weight of the funding cycle during which the payment is being made.
/// @custom:member reservedRate The reserved rate of the funding cycle during which the payment is being made.
/// @custom:member memo The memo that was sent alongside the payment.
/// @custom: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 20 of 49 : JBRedeemParamsData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBPaymentTerminal} from './../interfaces/IJBPaymentTerminal.sol';
import {JBTokenAmount} from './JBTokenAmount.sol';

/// @custom:member terminal The terminal that is facilitating the redemption.
/// @custom:member holder The holder of the tokens being redeemed.
/// @custom:member projectId The ID of the project whos tokens are being redeemed.
/// @custom:member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.
/// @custom:member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.
/// @custom:member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.
/// @custom:member overflow The amount of overflow used in the reclaim amount calculation.
/// @custom: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.
/// @custom:member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.
/// @custom:member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.
/// @custom:member memo The proposed memo that is being emitted alongside the redemption.
/// @custom: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 21 of 49 : JBRedemptionDelegateAllocation3_1_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBRedemptionDelegate3_1_1} from '../interfaces/IJBRedemptionDelegate3_1_1.sol';

/// @custom:member delegate A delegate contract to use for subsequent calls.
/// @custom:member amount The amount to send to the delegate.
/// @custom:member metadata Metadata to pass the delegate.
struct JBRedemptionDelegateAllocation3_1_1 {
  IJBRedemptionDelegate3_1_1 delegate;
  uint256 amount;
  bytes metadata;
}

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

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

File 23 of 49 : 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;
        }
    }
}

File 24 of 49 : 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 25 of 49 : JBFundAccessConstraints.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBPaymentTerminal} from './../interfaces/IJBPaymentTerminal.sol';

/// @custom:member terminal The terminal within which the distribution limit and the overflow allowance applies.
/// @custom:member token The token for which the fund access constraints apply.
/// @custom: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.
/// @custom:member distributionLimitCurrency The currency of the distribution limit.
/// @custom: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.
/// @custom:member overflowAllowanceCurrency The currency of the overflow allowance.
struct JBFundAccessConstraints {
  IJBPaymentTerminal terminal;
  address token;
  uint256 distributionLimit;
  uint256 distributionLimitCurrency;
  uint256 overflowAllowance;
  uint256 overflowAllowanceCurrency;
}

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

import {IJBFundingCycleBallot} from './../interfaces/IJBFundingCycleBallot.sol';

/// @custom: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`.
/// @custom: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.
/// @custom: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`.
/// @custom: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 27 of 49 : JBFundingCycleMetadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBGlobalFundingCycleMetadata} from './JBGlobalFundingCycleMetadata.sol';

/// @custom:member global Data used globally in non-migratable ecosystem contracts.
/// @custom:member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.
/// @custom:member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.
/// @custom: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`.
/// @custom:member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.
/// @custom:member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.
/// @custom:member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.
/// @custom:member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.
/// @custom:member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.
/// @custom:member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.
/// @custom:member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.
/// @custom:member holdFees A flag indicating if fees should be held during this funding cycle.
/// @custom:member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.
/// @custom: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.
/// @custom:member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.
/// @custom:member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.
/// @custom:member dataSource The data source to use during this funding cycle.
/// @custom: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 28 of 49 : JBGroupedSplits.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBSplit} from './JBSplit.sol';

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

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

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

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

import {IJBSplitAllocator} from './../interfaces/IJBSplitAllocator.sol';

/// @custom: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.
/// @custom:member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.
/// @custom:member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.
/// @custom: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.
/// @custom: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.
/// @custom:member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.
/// @custom: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 31 of 49 : IJBController3_0_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJBController3_0_1 {
  function reservedTokenBalanceOf(uint256 projectId) external view returns (uint256);

  function totalOutstandingTokensOf(uint256 projectId) external view returns (uint256);
}

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

import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import {JBFundAccessConstraints} from './../structs/JBFundAccessConstraints.sol';
import {IJBPaymentTerminal} from './IJBPaymentTerminal.sol';

interface IJBFundAccessConstraintsStore is IERC165 {
  event SetFundAccessConstraints(
    uint256 indexed fundingCycleConfiguration,
    uint256 indexed projectId,
    JBFundAccessConstraints constraints,
    address caller
  );

  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 setFor(
    uint256 projectId,
    uint256 configuration,
    JBFundAccessConstraints[] memory fundAccessConstaints
  ) external;
}

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

interface IJBMigratable {
  function prepForMigrationOf(uint256 projectId, address from) external;
}

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

import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import {JBProjectMetadata} from './../structs/JBProjectMetadata.sol';
import {IJBTokenUriResolver} from './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 35 of 49 : IJBSplitsStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBGroupedSplits} from './../structs/JBGroupedSplits.sol';
import {JBSplit} from './../structs/JBSplit.sol';
import {IJBDirectory} from './IJBDirectory.sol';
import {IJBProjects} from './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 36 of 49 : IJBTokenStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBFundingCycleStore} from './IJBFundingCycleStore.sol';
import {IJBProjects} from './IJBProjects.sol';
import {IJBToken} from './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 37 of 49 : IJBPriceFeed.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

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

/// @custom:member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.
/// @custom:member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.
/// @custom: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 39 of 49 : JBGlobalFundingCycleMetadataResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {JBFundingCycleMetadata} from './../structs/JBFundingCycleMetadata.sol';
import {JBGlobalFundingCycleMetadata} from './../structs/JBGlobalFundingCycleMetadata.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 40 of 49 : IJBFundingCycleBallot.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import {JBBallotState} from './../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 41 of 49 : IJBPayDelegate3_1_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import {JBDidPayData3_1_1} from './../structs/JBDidPayData3_1_1.sol';

/// @title Pay delegate
/// @notice Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)
interface IJBPayDelegate3_1_1 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 JBDidPayData3_1_1 struct:
  function didPay(JBDidPayData3_1_1 calldata data) external payable;
}

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

import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol';
import {JBDidRedeemData3_1_1} from './../structs/JBDidRedeemData3_1_1.sol';

/// @title Redemption delegate
/// @notice Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)
interface IJBRedemptionDelegate3_1_1 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:
  function didRedeem(JBDidRedeemData3_1_1 calldata data) external payable;
}

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

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

/// @title Split allocator
/// @notice Provide a way to process a single split with extra logic
/// @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:
  function allocate(JBSplitAllocationData calldata data) external payable;
}

File 44 of 49 : 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 45 of 49 : IJBTokenUriResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

File 46 of 49 : 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 47 of 49 : JBDidPayData3_1_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBTokenAmount} from './JBTokenAmount.sol';

/// @custom:member payer The address from which the payment originated.
/// @custom:member projectId The ID of the project for which the payment was made.
/// @custom:member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.
/// @custom: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.
/// @custom: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.
/// @custom:member projectTokenCount The number of project tokens minted for the beneficiary.
/// @custom:member beneficiary The address to which the tokens were minted.
/// @custom: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.
/// @custom:member memo The memo that is being emitted alongside the payment.
/// @custom:member dataSourceMetadata Extra data to send to the delegate sent by the data source.
/// @custom:member payerMetadata Extra data to send to the delegate sent by the payer.
struct JBDidPayData3_1_1 {
  address payer;
  uint256 projectId;
  uint256 currentFundingCycleConfiguration;
  JBTokenAmount amount;
  JBTokenAmount forwardedAmount;
  uint256 projectTokenCount;
  address beneficiary;
  bool preferClaimedTokens;
  string memo;
  bytes dataSourceMetadata;
  bytes payerMetadata;
}

File 48 of 49 : JBDidRedeemData3_1_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBTokenAmount} from './JBTokenAmount.sol';

/// @custom:member holder The holder of the tokens being redeemed.
/// @custom:member projectId The ID of the project with which the redeemed tokens are associated.
/// @custom:member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.
/// @custom:member projectTokenCount The number of project tokens being redeemed.
/// @custom: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.
/// @custom: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.
/// @custom:member beneficiary The address to which the reclaimed amount will be sent.
/// @custom:member memo The memo that is being emitted alongside the redemption.
/// @custom:member dataSourceMetadata Extra data to send to the delegate sent by the data source.
/// @custom:member redeemerMetadata Extra data to send to the delegate sent by the redeemer.
struct JBDidRedeemData3_1_1 {
  address holder;
  uint256 projectId;
  uint256 currentFundingCycleConfiguration;
  uint256 projectTokenCount;
  JBTokenAmount reclaimedAmount;
  JBTokenAmount forwardedAmount;
  address payable beneficiary;
  string memo;
  bytes dataSourceMetadata;
  bytes redeemerMetadata;
}

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

import {JBSplit} from './JBSplit.sol';

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

Settings
{
  "remappings": [
    "@chainlink/=node_modules/@chainlink/",
    "@ensdomains/=node_modules/@ensdomains/",
    "@juicebox/=contracts/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@paulrberg/=node_modules/@paulrberg/",
    "chainlink/=lib/chainlink/contracts/src/v0.8/dev/vendor/@arbitrum/nitro-contracts/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "eth-gas-reporter/=node_modules/eth-gas-reporter/",
    "forge-std/=lib/forge-std/src/",
    "hardhat-deploy/=node_modules/hardhat-deploy/",
    "hardhat/=node_modules/hardhat/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "prb-math/=node_modules/prb-math/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

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 IJBPayDelegate3_1_1","name":"delegate","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct JBPayDelegateAllocation3_1_1[]","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 IJBRedemptionDelegate3_1_1","name":"delegate","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct JBRedemptionDelegateAllocation3_1_1[]","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"}]

60e06040523480156200001157600080fd5b506040516200366a3803806200366a833981016040819052620000349162000070565b60016000556001600160a01b0392831660805290821660a0521660c052620000c4565b6001600160a01b03811681146200006d57600080fd5b50565b6000806000606084860312156200008657600080fd5b8351620000938162000057565b6020850151909350620000a68162000057565b6040850151909250620000b98162000057565b809150509250925092565b60805160a05160c0516134ea6200018060003960008181610273015281816106d201528181610c1c0152818161214c015261232901526000818161018b0152818161036f0152818161083f01528181610d0601528181610e1c0152818161120d015281816114d7015281816115a0015281816118d901528181611cdf01526123b00152600081816102390152818161041f0152818161105c01528181611782015281816119b201528181611f2201526121c801526134ea6000f3fe608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610295578063d4c3a8d2146102a8578063e7c8e3e3146102d9578063e8ba563a146102ee57600080fd5b8063c294b2f414610221578063c41c2f2414610234578063c66445971461025b578063d3419bf31461026e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101fb578063b753d7e91461020e57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f6101123660046125c3565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101556101503660046125ef565b61031f565b60405161013992919061267a565b6101766101713660046127fa565b6107f5565b604051610139949392919061290b565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d33660046129bd565b610cc5565b6101eb6101e63660046129d6565b610dd2565b6040516101399493929190612a77565b61012f610209366004612b12565b61149c565b61012f61021c3660046125ef565b611566565b61012f61022f366004612b44565b61157d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6101556102693660046125ef565b611892565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f6102a33660046125c3565b611cd6565b61012f6102b6366004612b93565b600360209081526000938452604080852082529284528284209052825290205481565b6102ec6102e7366004612bc8565b611db4565b005b61012f6102fc366004612b93565b600260209081526000938452604080852082529284528284209052825290205481565b610327612556565b60006002600054036103545760405162461bcd60e51b815260040161034b90612bea565b60405180910390fd5b60026000556040516321d1336160e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190612c31565b336000908152600360209081526040808320898452825280832082850151845290915281205491935090610418908690612cc7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161046b91815260200190565b602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ac9190612cda565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050d9190612cda565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610560573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105849190612cda565b6040518563ffffffff1660e01b81526004016105a39493929190612cf7565b6040805180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e39190612d1e565b91509150818311806105f3575081155b1561061157604051635b76558960e11b815260040160405180910390fd5b8086146106315760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106959190612d42565b90508087146107505761074b886106ae6012600a612e3f565b604051635268657960e11b8152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa158015610722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107469190612d42565b611dfd565b610752565b875b9450610760338a8884611eca565b851115610780576040516317e53f6760e11b815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c8352905220546107c4908690612e4b565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6107fd612556565b60006060806002600054036108245760405162461bcd60e51b815260040161034b90612bea565b60026000556040516321d1336160e11b8152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b39190612c31565b80519094506000036108d85760405163174b338d60e11b815260040160405180910390fd5b61010084015160481c6001908116036109045760405163a3bb913360e01b815260040160405180910390fd5b61010084015160009060521c600190811614801561093a5750600061092e86610100015160541c90565b6001600160a01b031614155b15610a8c576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e80360381019061097c9190612e5e565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610a0d86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610a389190612ecd565b6000604051808303816000875af1158015610a57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a7f9190810190613038565b955093509150610acd9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610b495760005b8451811015610b47576000858281518110610afa57610afa613169565b602002602001015160200151905080600014610b3e5782811115610b31576040516336a8da9360e11b815260040160405180910390fd5b610b3b8184612e4b565b92505b50600101610add565b505b8c60200135600003610b61575060009350610cae9050565b8015610bc8573360009081526001602090815260408083208f8452909152902054610b8d908290612cc7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610bdb575060009250610cae565b60408c0135600060608e01358c14610c8c57604051635268657960e11b815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c879190612d42565b610c97565b610c9782600a612e3f565b9050610ca88e602001358483611dfd565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610ce95760405162461bcd60e51b815260040161034b90612bea565b600260009081556040516321d1336160e11b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610d56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7a9190612c31565b610100810151909150604d1c600190811614610da9576040516373e4f05f60e11b815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b610dda612556565b6000606080600260005403610e015760405162461bcd60e51b815260040161034b90612bea565b60026000556040516321d1336160e11b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610e6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e909190612c31565b610100810151909450604a1c600190811603610ebf5760405163a97cf58f60e01b815260040160405180910390fd5b610ef3604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190612cda565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc09190612d42565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190612d42565b6101008b015190915060511c60019081161461104d57611048338f8c84611eca565b611058565b6110588e83836121a5565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016110a891815260200190565b602060405180830381865afa1580156110c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e99190612cda565b6001600160a01b031663c18f2d318f6040518263ffffffff1660e01b815260040161111691815260200190565b602060405180830381865afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190612d42565b9350838d111561117957604051625c579160e91b815260040160405180910390fd5b841561118f5761118c8e8b8f8789612387565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156111ef575060006111e388610100015160541c90565b6001600160a01b031614155b156113c657604051633157d5c760e21b8152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa15801561125c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611280919061317f565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d81526020018481526020018581526020018681526020016112ed8b6101000151600160519190911c81161490565b151581526020016000846002811115611308576113086131a0565b1461131b576113168b6124bf565b611324565b6113248b6124dc565b81526020018c81526020018b815250905061134489610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161136f91906131b6565b6000604051808303816000875af115801561138e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113b691908101906132ae565b91995090975095506113ca915050565b8893505b50508251849150156114245760005b83518110156114225760008482815181106113f6576113f6613169565b602002602001015160200151905080600014611419576114168184612cc7565b92505b506001016113d9565b505b3360009081526001602090815260408083208c845290915290205481111561145f576040516317e53f6760e11b815260040160405180910390fd5b8015611487573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036114ae5750600061155e565b828411156114be5750600061155e565b6040516321d1336160e11b8152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154b9190612c31565b905061155a8682878787612387565b9150505b949350505050565b60006115738484846121a5565b90505b9392505050565b6040516321d1336160e11b81526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190612c31565b9050600083611687576116828787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167d9190612d42565b611eca565b611754565b61175486886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ed9190612d42565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561172b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174f9190612d42565b6121a5565b9050806000036117695760009250505061155e565b604051632eec7b5560e11b8152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa1580156117d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f59190612cda565b6001600160a01b031663c18f2d31886040518263ffffffff1660e01b815260040161182291815260200190565b602060405180830381865afa15801561183f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118639190612d42565b905080861115611879576000935050505061155e565b6118868784888486612387565b98975050505050505050565b61189a612556565b60006002600054036118be5760405162461bcd60e51b815260040161034b90612bea565b60026000556040516321d1336160e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194d9190612c31565b61010081015190925060491c60019081160361197c5760405163861e9dcd60e01b815260040160405180910390fd5b3360009081526002602090815260408083208884528252808320855184529091528120546119ab908690612cc7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b81526004016119fe91815260200190565b602060405180830381865afa158015611a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3f9190612cda565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa09190612cda565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611af3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b179190612cda565b6040518563ffffffff1660e01b8152600401611b369493929190612cf7565b6040805180830381865afa158015611b52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b769190612d1e565b9150915081831180611b86575081155b15611ba457604051630236b92b60e21b815260040160405180910390fd5b808614611bc45760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c289190612d42565b9050808714611c4657611c41886106ae6012600a612e3f565b611c48565b875b3360009081526001602090815260408083208d8452909152902054909550851115611c86576040516317e53f6760e11b815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b6000611dab83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b8152600401611d2b91815260200190565b61012060405180830381865afa158015611d49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6d9190612c31565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611659573d6000803e3d6000fd5b90505b92915050565b336000908152600160209081526040808320858452909152902054611dda908290612cc7565b336000908152600160209081526040808320958352949052929092209190915550565b6000808060001985870985870292508281108382030391505080600003611e3757838281611e2d57611e2d6133ce565b0492505050611576565b838110611e6157604051631dcf306360e21b8152600481018290526024810185905260440161034b565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b0384166000908152600160209081526040808320868452909152812054808203611eff57600091505061155e565b604051632eec7b5560e11b81526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa158015611f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8d9190612cda565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fee9190612cda565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120659190612cda565b6040518563ffffffff1660e01b81526004016120849493929190612cf7565b6040805180830381865afa1580156120a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c49190612d1e565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906121029084612e4b565b905080158015906121135750858214155b1561218657612183816121286012600a612e3f565b604051635268657960e11b815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401610705565b90505b808411612194576000612198565b8084035b9998505050505050505050565b60405163d175415360e01b81526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261223791908101906133e4565b90506000805b82518110156122e25782818151811061225857612258613169565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161228d91815260200190565b602060405180830381865afa1580156122aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ce9190612d42565b6122d89083612cc7565b915060010161223d565b5060006001851461235d57604051635268657960e11b8152600160048201526024810186905260126044820152612358908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401610705565b61235f565b815b90508560121461237a57612375816012886124f9565b61237c565b805b979650505050505050565b60008284036123975750806124b6565b600080604051633157d5c760e21b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156123ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612423919061317f565b6002811115612434576124346131a0565b1461244757612442866124bf565b612450565b612450866124dc565b9050806000036124645760009150506124b6565b6000612471848787611dfd565b905061271082036124855791506124b69050565b6124b18161249f8861249986612710612e4b565b89611dfd565b6124a99085612cc7565b612710611dfd565b925050505b95945050505050565b60006028826101000151901c61ffff16612710611dae9190612e4b565b60006038826101000151901c61ffff16612710611dae9190612e4b565b6000828203612509575082611576565b828211156125375761251b8383612e4b565b61252690600a612e3f565b6125309085613473565b9050611576565b6125418284612e4b565b61254c90600a612e3f565b6125309085613492565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6001600160a01b03811681146125c057600080fd5b50565b600080604083850312156125d657600080fd5b82356125e1816125ab565b946020939093013593505050565b60008060006060848603121561260457600080fd5b505081359360208301359350604090920135919050565b805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0808201519083015260c0808201519083015260e0808201516001600160a01b03169083015261010090810151910152565b6101408101612689828561261b565b826101208301529392505050565b60008083601f8401126126a957600080fd5b50813567ffffffffffffffff8111156126c157600080fd5b6020830191508360208285010111156126d957600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561271a5761271a6126e0565b60405290565b6040516060810167ffffffffffffffff8111828210171561271a5761271a6126e0565b604051601f8201601f1916810167ffffffffffffffff8111828210171561276c5761276c6126e0565b604052919050565b600067ffffffffffffffff82111561278e5761278e6126e0565b50601f01601f191660200190565b60006127af6127aa84612774565b612743565b90508281528383830111156127c357600080fd5b828260208301376000602084830101529392505050565b600082601f8301126127eb57600080fd5b611dab8383356020850161279c565b600080600080600080600080888a0361014081121561281857600080fd5b8935612823816125ab565b98506080601f198201121561283757600080fd5b5060208901965060a0890135955060c0890135945060e089013561285a816125ab565b935061010089013567ffffffffffffffff8082111561287857600080fd5b6128848c838d01612697565b90955093506101208b013591508082111561289e57600080fd5b506128ab8b828c016127da565b9150509295985092959890939650565b60005b838110156128d65781810151838201526020016128be565b50506000910152565b600081518084526128f78160208601602086016128bb565b601f01601f19169290920160200192915050565b600061018080830161291d848961261b565b61012084018790526101408401919091528451908190526101a080840191600581901b850190910190602080880160005b838110156129a65787850361019f19018652815180516001600160a01b031686528381015184870152604090810151606091870182905290612992818801836128df565b97850197965050509082019060010161294e565b505050508381036101608501526124b181866128df565b6000602082840312156129cf57600080fd5b5035919050565b600080600080600060a086880312156129ee57600080fd5b85356129f9816125ab565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612a2457600080fd5b818801915088601f830112612a3857600080fd5b612a478983356020850161279c565b93506080880135915080821115612a5d57600080fd5b50612a6a888289016127da565b9150509295509295909350565b6000610180808301612a89848961261b565b61012084018790526101408401919091528451908190526101a080840191600581901b850190910190602080880160005b838110156129a65787850361019f19018652815180516001600160a01b031686528381015184870152604090810151606091870182905290612afe818801836128df565b978501979650505090820190600101612aba565b60008060008060808587031215612b2857600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215612b5a57600080fd5b8435612b65816125ab565b9350602085013592506040850135915060608501358015158114612b8857600080fd5b939692955090935050565b600080600060608486031215612ba857600080fd5b8335612bb3816125ab565b95602085013595506040909401359392505050565b60008060408385031215612bdb57600080fd5b50508035926020909101359150565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b8051612c2c816125ab565b919050565b60006101208284031215612c4457600080fd5b612c4c6126f6565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152612c9860e08401612c21565b60e0820152610100928301519281019290925250919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611dae57611dae612cb1565b600060208284031215612cec57600080fd5b8151611576816125ab565b93845260208401929092526001600160a01b03908116604084015216606082015260800190565b60008060408385031215612d3157600080fd5b505080516020909101519092909150565b600060208284031215612d5457600080fd5b5051919050565b600181815b80851115612d96578160001904821115612d7c57612d7c612cb1565b80851615612d8957918102915b93841c9390800290612d60565b509250929050565b600082612dad57506001611dae565b81612dba57506000611dae565b8160018114612dd05760028114612dda57612df6565b6001915050611dae565b60ff841115612deb57612deb612cb1565b50506001821b611dae565b5060208310610133831016604e8410600b8410161715612e19575081810a611dae565b612e238383612d5b565b8060001904821115612e3757612e37612cb1565b029392505050565b6000611dab8383612d9e565b81810381811115611dae57611dae612cb1565b600060808284031215612e7057600080fd5b6040516080810181811067ffffffffffffffff82111715612e9357612e936126e0565b6040528235612ea1816125ab565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b60208152612ee76020820183516001600160a01b03169052565b60006020830151612f0360408401826001600160a01b03169052565b506040830151612f3d606084018280516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b50606083015160e08301526080830151610100818185015260a08501519150610120612f73818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a0915081610180860152612fa96101c08601846128df565b90860151858203601f190183870152909250612fc583826128df565b9695505050505050565b600082601f830112612fe057600080fd5b8151612fee6127aa82612774565b81815284602083860101111561300357600080fd5b61155e8260208301602087016128bb565b600067ffffffffffffffff82111561302e5761302e6126e0565b5060051b60200190565b60008060006060848603121561304d57600080fd5b8351925060208085015167ffffffffffffffff8082111561306d57600080fd5b61307988838901612fcf565b9450604087015191508082111561308f57600080fd5b818701915087601f8301126130a357600080fd5b81516130b16127aa82613014565b81815260059190911b8301840190848101908a8311156130d057600080fd5b8585015b83811015613158578051858111156130ec5760008081fd5b86016060818e03601f190112156131035760008081fd5b61310b612720565b88820151613118816125ab565b81526040820151898201526060820151878111156131365760008081fd5b6131448f8b83860101612fcf565b6040830152508452509186019186016130d4565b508096505050505050509250925092565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561319157600080fd5b81516003811061157657600080fd5b634e487b7160e01b600052602160045260246000fd5b602081526131d06020820183516001600160a01b03169052565b600060208301516131ec60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e083015161010061325a8185018380516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b8401511515610180840152506101208301516101a08301526101408301516101e06101c084018190526132916102008501836128df565b9150610160850151601f198584030182860152612fc583826128df565b6000806000606084860312156132c357600080fd5b8351925060208085015167ffffffffffffffff808211156132e357600080fd5b6132ef88838901612fcf565b9450604087015191508082111561330557600080fd5b818701915087601f83011261331957600080fd5b81516133276127aa82613014565b81815260059190911b8301840190848101908a83111561334657600080fd5b8585015b83811015613158578051858111156133625760008081fd5b86016060818e03601f190112156133795760008081fd5b613381612720565b8882015161338e816125ab565b81526040820151898201526060820151878111156133ac5760008081fd5b6133ba8f8b83860101612fcf565b60408301525084525091860191860161334a565b634e487b7160e01b600052601260045260246000fd5b600060208083850312156133f757600080fd5b825167ffffffffffffffff81111561340e57600080fd5b8301601f8101851361341f57600080fd5b805161342d6127aa82613014565b81815260059190911b8201830190838101908783111561344c57600080fd5b928401925b8284101561237c578351613464816125ab565b82529284019290840190613451565b600081600019048311821515161561348d5761348d612cb1565b500290565b6000826134af57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212207c0b0d6ef21a30936e47f919249183a609014eddc061713ac513cccd6177f36164736f6c634300081000330000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a99000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b550000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610295578063d4c3a8d2146102a8578063e7c8e3e3146102d9578063e8ba563a146102ee57600080fd5b8063c294b2f414610221578063c41c2f2414610234578063c66445971461025b578063d3419bf31461026e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101fb578063b753d7e91461020e57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f6101123660046125c3565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101556101503660046125ef565b61031f565b60405161013992919061267a565b6101766101713660046127fa565b6107f5565b604051610139949392919061290b565b6101ad7f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b5581565b6040516001600160a01b039091168152602001610139565b61012f6101d33660046129bd565b610cc5565b6101eb6101e63660046129d6565b610dd2565b6040516101399493929190612a77565b61012f610209366004612b12565b61149c565b61012f61021c3660046125ef565b611566565b61012f61022f366004612b44565b61157d565b6101ad7f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a9981565b6101556102693660046125ef565b611892565b6101ad7f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c81565b61012f6102a33660046125c3565b611cd6565b61012f6102b6366004612b93565b600360209081526000938452604080852082529284528284209052825290205481565b6102ec6102e7366004612bc8565b611db4565b005b61012f6102fc366004612b93565b600260209081526000938452604080852082529284528284209052825290205481565b610327612556565b60006002600054036103545760405162461bcd60e51b815260040161034b90612bea565b60405180910390fd5b60026000556040516321d1336160e11b8152600481018690527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190612c31565b336000908152600360209081526040808320898452825280832082850151845290915281205491935090610418908690612cc7565b90506000807f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161046b91815260200190565b602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ac9190612cda565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050d9190612cda565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610560573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105849190612cda565b6040518563ffffffff1660e01b81526004016105a39493929190612cf7565b6040805180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e39190612d1e565b91509150818311806105f3575081155b1561061157604051635b76558960e11b815260040160405180910390fd5b8086146106315760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106959190612d42565b90508087146107505761074b886106ae6012600a612e3f565b604051635268657960e11b8152600481018b905260248101859052601260448201527f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c6001600160a01b03169063a4d0caf2906064015b602060405180830381865afa158015610722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107469190612d42565b611dfd565b610752565b875b9450610760338a8884611eca565b851115610780576040516317e53f6760e11b815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c8352905220546107c4908690612e4b565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6107fd612556565b60006060806002600054036108245760405162461bcd60e51b815260040161034b90612bea565b60026000556040516321d1336160e11b8152600481018b90527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa15801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b39190612c31565b80519094506000036108d85760405163174b338d60e11b815260040160405180910390fd5b61010084015160481c6001908116036109045760405163a3bb913360e01b815260040160405180910390fd5b61010084015160009060521c600190811614801561093a5750600061092e86610100015160541c90565b6001600160a01b031614155b15610a8c576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e80360381019061097c9190612e5e565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610a0d86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610a389190612ecd565b6000604051808303816000875af1158015610a57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a7f9190810190613038565b955093509150610acd9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610b495760005b8451811015610b47576000858281518110610afa57610afa613169565b602002602001015160200151905080600014610b3e5782811115610b31576040516336a8da9360e11b815260040160405180910390fd5b610b3b8184612e4b565b92505b50600101610add565b505b8c60200135600003610b61575060009350610cae9050565b8015610bc8573360009081526001602090815260408083208f8452909152902054610b8d908290612cc7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610bdb575060009250610cae565b60408c0135600060608e01358c14610c8c57604051635268657960e11b815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c169063a4d0caf290606401602060405180830381865afa158015610c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c879190612d42565b610c97565b610c9782600a612e3f565b9050610ca88e602001358483611dfd565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610ce95760405162461bcd60e51b815260040161034b90612bea565b600260009081556040516321d1336160e11b8152600481018490527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa158015610d56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7a9190612c31565b610100810151909150604d1c600190811614610da9576040516373e4f05f60e11b815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b610dda612556565b6000606080600260005403610e015760405162461bcd60e51b815260040161034b90612bea565b60026000556040516321d1336160e11b8152600481018990527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa158015610e6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e909190612c31565b610100810151909450604a1c600190811603610ebf5760405163a97cf58f60e01b815260040160405180910390fd5b610ef3604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190612cda565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc09190612d42565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190612d42565b6101008b015190915060511c60019081161461104d57611048338f8c84611eca565b611058565b6110588e83836121a5565b94507f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016110a891815260200190565b602060405180830381865afa1580156110c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e99190612cda565b6001600160a01b031663c18f2d318f6040518263ffffffff1660e01b815260040161111691815260200190565b602060405180830381865afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190612d42565b9350838d111561117957604051625c579160e91b815260040160405180910390fd5b841561118f5761118c8e8b8f8789612387565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156111ef575060006111e388610100015160541c90565b6001600160a01b031614155b156113c657604051633157d5c760e21b8152600481018c90526000907f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b03169063c55f571c90602401602060405180830381865afa15801561125c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611280919061317f565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d81526020018481526020018581526020018681526020016112ed8b6101000151600160519190911c81161490565b151581526020016000846002811115611308576113086131a0565b1461131b576113168b6124bf565b611324565b6113248b6124dc565b81526020018c81526020018b815250905061134489610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161136f91906131b6565b6000604051808303816000875af115801561138e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113b691908101906132ae565b91995090975095506113ca915050565b8893505b50508251849150156114245760005b83518110156114225760008482815181106113f6576113f6613169565b602002602001015160200151905080600014611419576114168184612cc7565b92505b506001016113d9565b505b3360009081526001602090815260408083208c845290915290205481111561145f576040516317e53f6760e11b815260040160405180910390fd5b8015611487573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036114ae5750600061155e565b828411156114be5750600061155e565b6040516321d1336160e11b8152600481018690526000907f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa158015611527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154b9190612c31565b905061155a8682878787612387565b9150505b949350505050565b60006115738484846121a5565b90505b9392505050565b6040516321d1336160e11b81526004810184905260009081906001600160a01b037f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b5516906343a266c29060240161012060405180830381865afa1580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190612c31565b9050600083611687576116828787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167d9190612d42565b611eca565b611754565b61175486886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ed9190612d42565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561172b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174f9190612d42565b6121a5565b9050806000036117695760009250505061155e565b604051632eec7b5560e11b8152600481018790526000907f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b031690635dd8f6aa90602401602060405180830381865afa1580156117d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f59190612cda565b6001600160a01b031663c18f2d31886040518263ffffffff1660e01b815260040161182291815260200190565b602060405180830381865afa15801561183f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118639190612d42565b905080861115611879576000935050505061155e565b6118868784888486612387565b98975050505050505050565b61189a612556565b60006002600054036118be5760405162461bcd60e51b815260040161034b90612bea565b60026000556040516321d1336160e11b8152600481018690527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b0316906343a266c29060240161012060405180830381865afa158015611929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194d9190612c31565b61010081015190925060491c60019081160361197c5760405163861e9dcd60e01b815260040160405180910390fd5b3360009081526002602090815260408083208884528252808320855184529091528120546119ab908690612cc7565b90506000807f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a996001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b81526004016119fe91815260200190565b602060405180830381865afa158015611a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3f9190612cda565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa09190612cda565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611af3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b179190612cda565b6040518563ffffffff1660e01b8152600401611b369493929190612cf7565b6040805180830381865afa158015611b52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b769190612d1e565b9150915081831180611b86575081155b15611ba457604051630236b92b60e21b815260040160405180910390fd5b808614611bc45760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c289190612d42565b9050808714611c4657611c41886106ae6012600a612e3f565b611c48565b875b3360009081526001602090815260408083208d8452909152902054909550851115611c86576040516317e53f6760e11b815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b6000611dab83837f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b03166343a266c2866040518263ffffffff1660e01b8152600401611d2b91815260200190565b61012060405180830381865afa158015611d49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6d9190612c31565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611659573d6000803e3d6000fd5b90505b92915050565b336000908152600160209081526040808320858452909152902054611dda908290612cc7565b336000908152600160209081526040808320958352949052929092209190915550565b6000808060001985870985870292508281108382030391505080600003611e3757838281611e2d57611e2d6133ce565b0492505050611576565b838110611e6157604051631dcf306360e21b8152600481018290526024810185905260440161034b565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b0384166000908152600160209081526040808320868452909152812054808203611eff57600091505061155e565b604051632eec7b5560e11b81526004810186905260009081906001600160a01b037f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a991690635dd8f6aa90602401602060405180830381865afa158015611f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8d9190612cda565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fee9190612cda565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120659190612cda565b6040518563ffffffff1660e01b81526004016120849493929190612cf7565b6040805180830381865afa1580156120a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c49190612d1e565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906121029084612e4b565b905080158015906121135750858214155b1561218657612183816121286012600a612e3f565b604051635268657960e11b815260048101869052602481018a9052601260448201527f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c6001600160a01b03169063a4d0caf290606401610705565b90505b808411612194576000612198565b8084035b9998505050505050505050565b60405163d175415360e01b81526004810184905260009081906001600160a01b037f0000000000000000000000008e05bcd2812e1449f0ec3ae24e2c395f533d9a99169063d175415390602401600060405180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261223791908101906133e4565b90506000805b82518110156122e25782818151811061225857612258613169565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161228d91815260200190565b602060405180830381865afa1580156122aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ce9190612d42565b6122d89083612cc7565b915060010161223d565b5060006001851461235d57604051635268657960e11b8152600160048201526024810186905260126044820152612358908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000009f0ec91d28ffc54874e9ff11a316ba2537acd72c169063a4d0caf290606401610705565b61235f565b815b90508560121461237a57612375816012886124f9565b61237c565b805b979650505050505050565b60008284036123975750806124b6565b600080604051633157d5c760e21b8152600481018990527f000000000000000000000000b9ee9d8203467f6ec0eac81163d210bd1a7d3b556001600160a01b03169063c55f571c90602401602060405180830381865afa1580156123ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612423919061317f565b6002811115612434576124346131a0565b1461244757612442866124bf565b612450565b612450866124dc565b9050806000036124645760009150506124b6565b6000612471848787611dfd565b905061271082036124855791506124b69050565b6124b18161249f8861249986612710612e4b565b89611dfd565b6124a99085612cc7565b612710611dfd565b925050505b95945050505050565b60006028826101000151901c61ffff16612710611dae9190612e4b565b60006038826101000151901c61ffff16612710611dae9190612e4b565b6000828203612509575082611576565b828211156125375761251b8383612e4b565b61252690600a612e3f565b6125309085613473565b9050611576565b6125418284612e4b565b61254c90600a612e3f565b6125309085613492565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6001600160a01b03811681146125c057600080fd5b50565b600080604083850312156125d657600080fd5b82356125e1816125ab565b946020939093013593505050565b60008060006060848603121561260457600080fd5b505081359360208301359350604090920135919050565b805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0808201519083015260c0808201519083015260e0808201516001600160a01b03169083015261010090810151910152565b6101408101612689828561261b565b826101208301529392505050565b60008083601f8401126126a957600080fd5b50813567ffffffffffffffff8111156126c157600080fd5b6020830191508360208285010111156126d957600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561271a5761271a6126e0565b60405290565b6040516060810167ffffffffffffffff8111828210171561271a5761271a6126e0565b604051601f8201601f1916810167ffffffffffffffff8111828210171561276c5761276c6126e0565b604052919050565b600067ffffffffffffffff82111561278e5761278e6126e0565b50601f01601f191660200190565b60006127af6127aa84612774565b612743565b90508281528383830111156127c357600080fd5b828260208301376000602084830101529392505050565b600082601f8301126127eb57600080fd5b611dab8383356020850161279c565b600080600080600080600080888a0361014081121561281857600080fd5b8935612823816125ab565b98506080601f198201121561283757600080fd5b5060208901965060a0890135955060c0890135945060e089013561285a816125ab565b935061010089013567ffffffffffffffff8082111561287857600080fd5b6128848c838d01612697565b90955093506101208b013591508082111561289e57600080fd5b506128ab8b828c016127da565b9150509295985092959890939650565b60005b838110156128d65781810151838201526020016128be565b50506000910152565b600081518084526128f78160208601602086016128bb565b601f01601f19169290920160200192915050565b600061018080830161291d848961261b565b61012084018790526101408401919091528451908190526101a080840191600581901b850190910190602080880160005b838110156129a65787850361019f19018652815180516001600160a01b031686528381015184870152604090810151606091870182905290612992818801836128df565b97850197965050509082019060010161294e565b505050508381036101608501526124b181866128df565b6000602082840312156129cf57600080fd5b5035919050565b600080600080600060a086880312156129ee57600080fd5b85356129f9816125ab565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612a2457600080fd5b818801915088601f830112612a3857600080fd5b612a478983356020850161279c565b93506080880135915080821115612a5d57600080fd5b50612a6a888289016127da565b9150509295509295909350565b6000610180808301612a89848961261b565b61012084018790526101408401919091528451908190526101a080840191600581901b850190910190602080880160005b838110156129a65787850361019f19018652815180516001600160a01b031686528381015184870152604090810151606091870182905290612afe818801836128df565b978501979650505090820190600101612aba565b60008060008060808587031215612b2857600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215612b5a57600080fd5b8435612b65816125ab565b9350602085013592506040850135915060608501358015158114612b8857600080fd5b939692955090935050565b600080600060608486031215612ba857600080fd5b8335612bb3816125ab565b95602085013595506040909401359392505050565b60008060408385031215612bdb57600080fd5b50508035926020909101359150565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b8051612c2c816125ab565b919050565b60006101208284031215612c4457600080fd5b612c4c6126f6565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152612c9860e08401612c21565b60e0820152610100928301519281019290925250919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611dae57611dae612cb1565b600060208284031215612cec57600080fd5b8151611576816125ab565b93845260208401929092526001600160a01b03908116604084015216606082015260800190565b60008060408385031215612d3157600080fd5b505080516020909101519092909150565b600060208284031215612d5457600080fd5b5051919050565b600181815b80851115612d96578160001904821115612d7c57612d7c612cb1565b80851615612d8957918102915b93841c9390800290612d60565b509250929050565b600082612dad57506001611dae565b81612dba57506000611dae565b8160018114612dd05760028114612dda57612df6565b6001915050611dae565b60ff841115612deb57612deb612cb1565b50506001821b611dae565b5060208310610133831016604e8410600b8410161715612e19575081810a611dae565b612e238383612d5b565b8060001904821115612e3757612e37612cb1565b029392505050565b6000611dab8383612d9e565b81810381811115611dae57611dae612cb1565b600060808284031215612e7057600080fd5b6040516080810181811067ffffffffffffffff82111715612e9357612e936126e0565b6040528235612ea1816125ab565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b60208152612ee76020820183516001600160a01b03169052565b60006020830151612f0360408401826001600160a01b03169052565b506040830151612f3d606084018280516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b50606083015160e08301526080830151610100818185015260a08501519150610120612f73818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a0915081610180860152612fa96101c08601846128df565b90860151858203601f190183870152909250612fc583826128df565b9695505050505050565b600082601f830112612fe057600080fd5b8151612fee6127aa82612774565b81815284602083860101111561300357600080fd5b61155e8260208301602087016128bb565b600067ffffffffffffffff82111561302e5761302e6126e0565b5060051b60200190565b60008060006060848603121561304d57600080fd5b8351925060208085015167ffffffffffffffff8082111561306d57600080fd5b61307988838901612fcf565b9450604087015191508082111561308f57600080fd5b818701915087601f8301126130a357600080fd5b81516130b16127aa82613014565b81815260059190911b8301840190848101908a8311156130d057600080fd5b8585015b83811015613158578051858111156130ec5760008081fd5b86016060818e03601f190112156131035760008081fd5b61310b612720565b88820151613118816125ab565b81526040820151898201526060820151878111156131365760008081fd5b6131448f8b83860101612fcf565b6040830152508452509186019186016130d4565b508096505050505050509250925092565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561319157600080fd5b81516003811061157657600080fd5b634e487b7160e01b600052602160045260246000fd5b602081526131d06020820183516001600160a01b03169052565b600060208301516131ec60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e083015161010061325a8185018380516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b8401511515610180840152506101208301516101a08301526101408301516101e06101c084018190526132916102008501836128df565b9150610160850151601f198584030182860152612fc583826128df565b6000806000606084860312156132c357600080fd5b8351925060208085015167ffffffffffffffff808211156132e357600080fd5b6132ef88838901612fcf565b9450604087015191508082111561330557600080fd5b818701915087601f83011261331957600080fd5b81516133276127aa82613014565b81815260059190911b8301840190848101908a83111561334657600080fd5b8585015b83811015613158578051858111156133625760008081fd5b86016060818e03601f190112156133795760008081fd5b613381612720565b8882015161338e816125ab565b81526040820151898201526060820151878111156133ac5760008081fd5b6133ba8f8b83860101612fcf565b60408301525084525091860191860161334a565b634e487b7160e01b600052601260045260246000fd5b600060208083850312156133f757600080fd5b825167ffffffffffffffff81111561340e57600080fd5b8301601f8101851361341f57600080fd5b805161342d6127aa82613014565b81815260059190911b8201830190838101908783111561344c57600080fd5b928401925b8284101561237c578351613464816125ab565b82529284019290840190613451565b600081600019048311821515161561348d5761348d612cb1565b500290565b6000826134af57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212207c0b0d6ef21a30936e47f919249183a609014eddc061713ac513cccd6177f36164736f6c63430008100033

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.